Reputation: 928
I have a simplified version of my problem as follows:
const Component = () => {
const [data, setData] = useState([]);
const fn = useCallback((num) => {
const newData = [...data];
newData.push(num);
setData(newData);
}, [data]);
return <button onClick={() => fn(Math.random())}>{data.join()}</button>;
};
My problem is that newData
is always []
, instead of reflecting the updated state values. Therefore, my button will only show the latest data
value instead of an array with increasing values. Why is this the case as I've included it in the dependency array of the useCallback
function?
Upvotes: 6
Views: 8566
Reputation: 6008
I guess the problem is most probably happen in the "button" component which you have simplified in your question therefore we cannot see the real problem.
There could be multiple reasons why states in the "useCallback" is not updated:
you didn't add the state in the dependency of "useCallback". This is not your case as you already add data in the dependency
you use this "fn" in another "useCallback" and you didn't add fn as a dependency of that "useCallback".
// what you probably write in the "button" component
const handleClick = useCallback(() => {
...
doSomethingWithState(someState);
props.onClick(); //<--- this is the fn you passed
}, [someState]);
// what you should write
const handleClick = useCallback(() => {
...
doSomethingWithState(someState);
props.onClick(); //<--- this is the fn you passed
}, [someState, props.onClick]); //<---- you need to add the method as dependency as well
please verify if this is your case.
Upvotes: 8
Reputation: 8548
Your code works just as you expect:
https://codesandbox.io/s/relaxed-ishizaka-n2eg6?file=/src/App.js
It does show the updated state values.
Upvotes: 0