I have a doubt regarding, how hooks like useCallback() work when the variables, arrow functions, and states used in it and its dependency, are declared before and after the useCallback().
Note: The code is processed through Babel, which transforms it to ES5. This means all const and let declarations are converted to var.
Scenario 1
function App() {
const [counter, setCounter] = useState(0);
const increment = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
const decrement = useCallback(() => {
setCounter(counter - 1);
}, [counter]);
//question snippet below
const incrementOtherCounter = useCallback(() => {
console.log("runner value :", runner());
console.log("this is otherCounter:", otherCounter);
setOtherCounter(otherCounter + 1);
}, [otherCounter, runner]);
const [otherCounter, setOtherCounter] = useState(0);
const runner = () => {
return "Something ran! :" + counter;
};
//question snippet above
return (
<div className="App">
<button onClick={decrement}>Decrement</button>
{` ${counter} `}
<button onClick={increment}>Increment</button>
<button onClick={incrementOtherCounter}>incrementOtherCounter</button>
</div>
);
}
In this scenario, whenever I run the incrementOtherCounter() function the result is as follows
runner value :Something ran! :0
this is otherCounter: 0
And no matter if update/increment the counter state or rerun the incrementOtherCounter() the result stays the same (counter and otherCounter remain 0).
Scenario 2
function App() {
const [counter, setCounter] = useState(0);
const increment = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
const decrement = useCallback(() => {
setCounter(counter - 1);
}, [counter]);
//question snippet below
const [otherCounter, setOtherCounter] = useState(0);
const incrementOtherCounter = useCallback(() => {
console.log("runner value :", runner());
console.log("this is otherCounter:", otherCounter);
setOtherCounter(otherCounter + 1);
}, [otherCounter, runner]);
const runner = () => {
return "Something ran! :" + counter;
};
//question snippet above
return (
<div className="App">
<button onClick={decrement}>Decrement</button>
{` ${counter} `}
<button onClick={increment}>Increment</button>
<button onClick={incrementOtherCounter}>incrementOtherCounter</button>
</div>
);
}
In this scenario, running the incrementOtherCounter() produces the correct output (as if runner() and otherCounter state is defined before incrementOtherCounter()), but the counter state in runner() arrow function, seems to lag behind the actual state updates. For instance, if I increment the counter, the runner() function returns the state with a delay of one update cycle.
Scenario 3
function App() {
const [counter, setCounter] = useState(0);
const increment = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
const decrement = useCallback(() => {
setCounter(counter - 1);
}, [counter]);
//question snippet below
const runner = () => {
return "Something ran! :" + counter;
};
const incrementOtherCounter = useCallback(() => {
console.log("runner value :", runner());
console.log("this is otherCounter:", otherCounter);
setOtherCounter(otherCounter + 1);
}, [otherCounter, runner]);
const [otherCounter, setOtherCounter] = useState(0);
//question snippet above
return (
<div className="App">
<button onClick={decrement}>Decrement</button>
{` ${counter} `}
<button onClick={increment}>Increment</button>
<button onClick={incrementOtherCounter}>incrementOtherCounter</button>
</div>
);
}
In this scenario,everything seems fine as if i have declared the runner() and otherCounter on top of the incrementOtherCounter().
I am not able to understand how things are working in scenarios 2 and 3 i.e how is incrementOtherCounter() producing correct values of counter and otherCounter in scenario 3 and lags behind one cycle in scenario 2?


ReferenceError. If it doesn’t, your implementation is not doing the right thing. What JavaScript engine are you using? If NodeJS, what version of NodeJS?constproblem. Until you get the correct variable values, it is moot to discuss how react works.useCallback()work when the variables, arrow functions, and states used in it and its dependency, are declared after theuseCallback()" - they work in the same way as if you simply haven't passed the dependency, or writtenundefinedin the dependency array. The dependency is therefore broken.