Home > Net >  List not rendering even when the array is not empty and the state is not null
List not rendering even when the array is not empty and the state is not null

Time:06-20

I am trying to retrieve Game names from firestore and display in a list on the page. For this I am using a component GameList(to display the names retrieved) and Home(to fetch and pass the retrieved data to GameList component).

Here is my code : Home.js :-

import { useState, useEffect } from 'react';
import { personalDatabaseFirestore } from '../firebase/personalConfig';
import GameList from './GameList';
import './Home.css'

export default function Home(){

const [data, setData] = useState(null);


useEffect(()=>{

    const ref = personalDatabaseFirestore.collection('Games');
    let results = []

    const unsub = ref.onSnapshot((snapshot)=>{
        snapshot.docs.forEach((doc) => {
            results.push({...doc.data(), id: doc.id});
        })
    },(error)=>{
        console.log(error);
    })
    setData(results);
    return ()=>unsub();
},[]);

console.log(data);

return (
    <div className='mainpage-container'>
        {data && <GameList games={data}/>}
    </div>
);

}

GameList.js :-

export default function GameList({games}){
  console.log('game list recieved\n', games);
  return (
      <ul>
          {
              games.map((doc)=>{
                  return (<li key={doc.id}>{doc.name}</li>);
              })
          }
      </ul>
  )
}

Console screenshot shows that i am able to retrieve the data successfully from firestore and am able to pass it to GameList component too . But then after logging out the information in gameList component it is not rendering the list that it is supposed to return.

enter image description here

CodePudding user response:

The onSnapshot() returns data asynchronously so you should use setData within it. That'll also ensure any data updates received later are also rendered. Try refactoring the code as shown below:

useEffect(() => {
  const ref = personalDatabaseFirestore.collection('Games');
  
  const unsub = ref.onSnapshot((snapshot) => {
    const results = snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }))
    setData(results);
  })
  return () => unsub();
}, []);

If you need to fetch data only once, then I'd recommend using get() instead of onSnapshot:

useEffect(() => {
  const ref = personalDatabaseFirestore.collection('Games');

  const fetchData = async () => {
    const snapshot = await ref.get();
    const results = snapshot.docs.map((doc) => ({
      id: doc.id,
      ...doc.data()
    }))
    setData(results);
  }
  
  fetchData();
}, []);
  • Related