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?
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?
Share Improve this question edited Sep 9, 2020 at 15:47 GeForce RTX 4090 asked Sep 9, 2020 at 15:23 GeForce RTX 4090GeForce RTX 4090 3,49812 gold badges35 silver badges65 bronze badges 6 | Show 1 more comment3 Answers
Reset to default 11You can use the useEffect
hook:
useEffect(() => {
//your code
}, [data]);
That will trigger what is inside every time data
changes.
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.
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
data
is still declared withconst
- it won't change – CertainPerformance Commented Sep 9, 2020 at 15:24data
– F.P Commented Sep 9, 2020 at 15:25