0

I have a component that gets an array of objects from a database using an async - await function. When the function gets the data and sets the array to a State variable, the component doesn't seem to update and I get errors about being unable to read properties. The data is being retrieved from the database correctly because I can console.log it. What am I doing wrong?

export default function LevelLeaderboard ({ level }) {
  const [leaderboardData, setLeaderboardData] = useState([])

  useEffect(()=>{
    getLeaderBoardData(level)
    .then((data)=>{
      console.log(data)
      setLeaderboardData(data)
    })
  },[level]);

  return (
    <div id="level" className="level-leaderboard">
      <ul>
      <li>{leaderboardData[0]['name']}</li>
      </ul>
    </div>       
  )
}

Error:

LevelLeaderboard.js:19 Uncaught TypeError: Cannot read properties of undefined (reading '0') at LevelLeaderboard (LevelLeaderboard.js:19:1) at renderWithHooks (react-dom.development.js:16305:1) at mountIndeterminateComponent (react-dom.development.js:20074:1) at beginWork (react-dom.development.js:21587:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at beginWork$1 (react-dom.development.js:27451:1) at performUnitOfWork (react-dom.development.js:26557:1) at workLoopSync (react-dom.development.js:26466:1)

Here's the async function:

export async function getLeaderBoardData(level, handleData){
  const querySnapshot = await getDocs(collection(leaderboard, level));
  let tempArr = [];
  querySnapshot.forEach((doc) => {
    tempArr.push(doc.data())
  });
  return tempArr;
}
2
  • The array will be empty on first render so you need to conditionally handle it leaderboardData[0]?.name (better to do it higher up in the html, but that should at least let it render once updated) Commented Feb 7, 2023 at 1:16
  • Also you can simplify your getLeaderBoardData by leveraging map(): return querySnapshot.map(doc => doc.data()); Commented Feb 7, 2023 at 1:23

1 Answer 1

0

You should add a conditional rendering to

<li>{leaderboardData[0]['name']}</li>

something like:

{leaderboardData.length >= 1 && <li>{leaderboardData[0]['name']}</li>}

since the array 'leaderboardData' its empty when component first render

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.