0

I'm using React and Firestore.
I want to get the value recorded in Firestore and setState to the retrieved value.
The current code is as follows.

const [value, setValue] = useState("");
useEffect(() => {
  db.collection("value")
    .doc(uid)
    .collection("subvalue")
    .onSnapshot(async (snapshot) => {
      snapshot.forEach((doc) => {
        const rawValue = doc.data().raw_value;
        setValue(rawValue);
        console.log(value);
      });
    });
}, []);

return <p>{value}</p>

In this code, value is empty.
Checking the console, it is also empty. (It doesn't show up as null or undefind, just empty.

console

However, when I ran console.log(rawValue) in forEach, the value was displayed in the console.

useEffect(() => {
  db.collection("value")
    .doc(uid)
    .collection("subvalue")
    .onSnapshot(async (snapshot) => {
      snapshot.forEach((doc) => {
        const rawValue = doc.data().raw_value;
        console.log(rawValue);
        setValue(rawValue);
      });
    });
}, []);

console

foo

This shows that the value is not empty, but exists, and that we are setState the value that exists.

I feel like I'm making some elementary mistakes, but I think what I'm doing is simple.

  • Get the value ← Yes.
  • value is not empty ← That's right.
  • Set the value ← Not done.

What's going on in the last step?

C.V.Alkan
  • 79
  • 1
  • 7
  • 1
    React state changes are not synchronous, they are batched for better performance. This is well documented both in the official docs and here on stack overflow. You will not see the updated value until the component re-renders. – Jared Smith Mar 17 '21 at 11:16

1 Answers1

1

state updation in React is async. So setting it inside a for Each won't work as expected

useEffect(() => {
  db.collection("value")
    .doc(uid)
    .collection("subvalue")
    .onSnapshot(async (snapshot) => {
      const finalSnapShot = [];
      snapshot.forEach((doc) => {
        const rawValue = doc.data().raw_value;
        finalSnapShot.push(rawValue); 
        console.log(rawValue)
      });
      setValue(finalSnapShot.join(',')); // would set a string with comma seperated value. You can update the way you want to set data to state
    });
}, []);
Erick
  • 1,098
  • 10
  • 21