Does the order of useCallback function declaration matters? For example:
Functions declared in this order:
const aboveFunction = useCallback(()=>{ logCount() },[logCount])
const logCount = useCallback(()=>{ console.log(count) },[count])
const belowFunction = useCallback(()=>{ logCount() },[logCount])
Notice both aboveFunction
and belowFunction
refers to the same logCount
.
After we call setCount(2)
,
aboveFunction()
-> logCount()
-> count
// 0, wheres
belowFunction()
-> logCount()
-> count
// 2
https://codesandbox.io/s/react-hooks-counter-demo-forked-7mofy?file=/src/index.js
/**
Click increment button until count is 2, then click
Above and Below button and check console log
* Even though the count value is > 0, aboveIncrement console.log(count) still gives 0
*/
import React, { useState, useCallback } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [count, setCount] = useState(0);
/** Assuming all the functions below do some intensive stuffs to justify useCallback */
const aboveFunction = useCallback(() => {
// ...do other intensive stuff
logCount("Above count:"); // Above count: 0
}, [logCount]);
const logCount = useCallback(
(str) => {
// ...do other intensive stuff
console.log(str, count);
},
[count]
);
const belowFunction = useCallback(() => {
// ...do other intensive stuff
logCount("Below count:"); // Above count: 2
}, [logCount]);
return (
<div className="App">
<h1>
Click increment button until count is 2, then click Above/ Below button
and see console log
</h1>
<h2>You clicked {count} times!</h2>
<div
style={{
display: "flex",
alignItems: "center",
flexDirection: "column"
}}
>
<button style={{ margin: 10 }} onClick={aboveFunction}>
Above Increment Function
</button>
<button style={{ margin: 10 }} onClick={() => setCount(count + 1)}>
Increment
</button>
<button style={{ margin: 10 }} onClick={belowFunction}>
Below Increment Function
</button>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
It is apparent that the order of useCallback declaration is important in order for the code to work. However, if we write it this way https://codesandbox.io/s/react-hooks-counter-demo-forked-7mofy?file=/src/index1.js
let logCount;
const aboveFunction = useCallback(() => {
logCount("Above count:"); // Above count: 0
}, [logCount]);
logCount = useCallback((str) => {
console.log(str, count);
}, [count]
);
const belowFunction = useCallback(() => {
logCount("Below count:"); // Above count: 2
}, [logCount]);
aboveFunction
still gives stale count value. Is there any rule-of-hooks that I'm missing?
Yes a fix here is to apply eslint no-use-before-define
. But I wanna understand the reason why .. isn’t functions get hoisted up in JavaScript and the order in which it is declared doesn’t matter?