Imagine you have this scenario
useEffect(() => {
console.log('query changed');
setSomething(1)
getStuff();
}, [props.match.params.query])
const getStuff = async () => {
console.log(something)
}
I've found in this scenario that something will always be the previous value. So for example if you change the props and something is 2, it will call setSomething(1), and put it into the queue. However, by the time you're inside getStuff, something will still be 2. How do you make it so that the setState function always applies before the next function is called?
CodePudding user response:
Your function getStuff is async
you need to use await, wrap that function in another function and invoke that
useEffect(() => {
console.log('query changed');
const getData=()=>{
setSomething(1)
await getStuff();
}
getData()
}, [props.match.params.query])
you can not see the change in useEffect because useState is async, you need to put more bottom your console
console.log(something)
return (
<div></div>
)
CodePudding user response:
The thing is when you call getStuff
it accesses the outdated state value. To get the actual one you could use useCallback
which creates a function binded with the updated state value.
export default function App() {
const [something, setSomething] = useState();
const [query, setQuery] = useState(0);
const getStuff = useCallback(() => {
console.log("something", something);
}, [something]);
useEffect(() => {
console.log("query changed");
setSomething(query);
getStuff();
}, [query, getStuff]);
console.log("query", query);
return (
<div className="App">
<button
onClick={() => {
setQuery(Math.random());
}}
>
Change
</button>
</div>
);
}
Does it solve your problem?
You could check it here https://codesandbox.io/s/naughty-lewin-rsvh5?file=/src/App.js:82-634