Description
The problem is that hooks mix the concept of dependence and effect. An effect execution may need the fresh value of a state but doesn't want the changing of the state trigger the execution. So the state has a confusing place to set. Should the state appear in dependency array? Please check code blow:
const [state1, setState1] = useState(5);
const [dependence1, setDependence1] = useState(10);
const [dependence2, setDependence2] = useState(15);
useEffect(() => {
// I want any changing of dependence1 or dependence2 will trigger
// the code execution here. And code here need fresh value of
// state1 but I don't want changing of state1 trigger execution.
console.log(dependence1 + dependence2 + state1);
}, [dependence1, dependence2]);
A solution hooks provided is use reference to 'boxing' the state.
const [state1, setState1] = useState(5);
const [dependence1, setDependence1] = useState(10);
const [dependence2, setDependence2] = useState(15);
const state1Ref = useRef(null);
useEffect(() => {
state1Ref.current = state1;
}, [state1]);
useEffect(() => {
console.log(dependence1 + dependence2 + state1Ref.current);
}, [dependence1, dependence2, state1Ref]);
As I know, the mentioned problem could be encountered very often, so It would be nice that react hooks provide a hook like useStateRef
to solve the problem. useStateRef
return an array which containing 3 elements, the first two are identical with useState
, the last one is a reference of the state, and the reference .current
keeps fresh. Like code below:
const [state1, setState1, state1Ref] = useStateRef(5);
const [dependence1, setDependence1] = useState(10);
const [dependence2, setDependence2] = useState(15);
useEffect(() => {
console.log(dependence1 + dependence2 + state1Ref.current);
}, [dependence1, dependence2, state1Ref]);
So as useCallbackRef
which is more useful I think.