GeForce RTX 4090
GeForce RTX 4090

Reputation: 3508

React hooks - wait until the state has been updated

I'm using the useState() hook, and I've found that my app has a bug, because setting the value is asynchronous. So if I have code like this:

 const [data, setData] = useState([])
  useEffect(() => {
    const getData = async () => {
      const res = await fetchData()
      console.log(data); // []
      setData(res.data.hits);
      console.log(res.data.hits); // Array full of objects
      console.log(data); // Still []
    }
    getData()
  }, [fetchData]);

How can I execute some specific logic only when the new state has actually been set?

Upvotes: 11

Views: 18229

Answers (3)

DanteDX
DanteDX

Reputation: 1259

With react 18, useEffect runs twice, but even with that, your logic will work here!

 const [data, setData] = useState([])
  useEffect(() => {
    const getData = async () => {
      const res = await fetchData()
      setData(res.data.hits);
    }
    if(!data.length){
      // logic for the time, when the state has not been updated yet
      getData()
    }else if(data.length){
      // logic for the time, when the state has been updated
      console.log("state is", state)
    }
  }, [data]); // only use [data], no need to put fetchData in the array

Upvotes: 0

Emmanuel Oyekan
Emmanuel Oyekan

Reputation: 1

You can perform some logic to ensure the "specific logic" you want is executed after your setData is done from that specific call and not from other setData calls,

For example,

 const [data, setData] = useState([])
 const [runSpecific, setRunSpecific] = useState(false)
  useEffect(() => {
    const getData = async () => {
      const res = await fetchData()
      console.log(data); // []
      setData(res.data.hits);
      setRunSpecific(true);
      console.log(res.data.hits); // Array full of objects
      console.log(data); // Still []
    }
    getData()
  }, [fetchData]);

  useEffect(() => {
    if(runSpecific){
       "specific Logic" you want to run
    }
    setRunSpecific(false)
  }, [data]);

In essence, every time the data changes, it executes your "specific logic" only when runSpecific is true, which can only be true from that initial call.

So you need not worry when about other SetData calls.

Upvotes: 0

Nico_
Nico_

Reputation: 1386

You can use the useEffect hook:

useEffect(() => {
   //your code
}, [data]);

That will trigger what is inside every time data changes.

Upvotes: 11

Related Questions