I was just wondering how come useCallback cannot pick up the latest state value from the component. Isn't component's state is present in the outer scope.
const [x, updateX] = useState(2);
const handleChange = useCallback(() => {
console.log(x);
// To pick up latest value of x in here, I need to add x in dependency array?
// Why is that this inner arrow function cannot pick x from its outer scope?
}, [])
Edit: The useRef latest value is picked up by the handleChange ..without needing the ref in the dependency array. However we need state value in dependencyArray. Why is that?
I guess there has to be some local scope in between getting created under the hood which is where the value of x is picked up from ? Not sure if I am correct.
Also, follow up question is how to write something like useCallback (function memoization)? using vanilla js ?
Yes, you need to pass X in the dependency array. The callback only gets changed when the dependency changes. In this example you can count up and log the current state of x.
function Tester(props: TesterProps): JSX.Element {
const [x, setX] = useState(0);
const handleChange = useCallback(() => {
console.log(x);
}, [x]);
return (
<>
<button onClick={() => setX(x + 1)}>Change State</button>
<button onClick={() => handleChange()}>Handle Change</button>
</>
);
}
Either do this:
const handleChange = useCallback(() => {
console.log(x);
}, [x]);
Or this:
const handleChange = () => {
console.log(x);
};
Both will print actual X value. The second one doesnt memoize the function, so it will be redeclared each render.