skip to Main Content

I am currently working on a simple todo crud app. I just cannot seem to get my data to be put out on the screen.

const Home = () => {

  const [todos,setTodos] = useState([]);

  const getTodos = async () =>{
    const querySnapshot = await getDocs(collection(db, "todos"));
    
    querySnapshot.forEach((doc) => {        
      setTodos([...todos,doc.data()])
      console.log(doc.data())
      console.log(todos)
    });  
  }

  useEffect(()=>{  
    getTodos();    
  },[])

  return (    
    <div>Home</div>
  )
}

Now the console.log(doc.data()) shows every dataset alright, but the todos array either gets just the first value assigned or returns an empty array.

Any ideas?

2

Answers


  1. instead of using setTodos([...todos,doc.data()])

    try this

    querySnapshot.forEach((doc) => {        
          setTodos((prev) => [...prev, doc.data()])
          console.log(doc.data())
          console.log(todos)
        });  
    
    Login or Signup to reply.
  2. State setter operations are asynchronous, calling setTodos doesn’t change what’s in the array your todos variable points to. Instead, it schedules a new call to your component function in which you’ll get the new data from useState. (More in this answer.) That’s why both your console.log(todos) and your repeated calls to setTodos aren’t working: Both are using oudated information from todos.

    When setting state based on existing state (your current array), it’s usually best to use the callback form of the state setter. So the minimal change would be:

    // But keep reading!
    querySnapshot.forEach((doc) => {        
        setTodos((todos) => [...todos, doc.data()]);
    });
    

    That would work, but rather than calling setTodos in a loop, you might want to do the loop and then call the setter once when you’re done.

    I don’t use Firebase, but Nick Parsons found and posted this link saying you can get the docs as an array via a docs property. So you can call map on that array:

    setTodos((todos) => [...todos, ...querySnapshot.docs.map((doc) => doc.data())]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search