const movingRef = useRef(false);
const handleStartMove = (e) => {
movingRef.current = true;
e.stopPropagation();
// handleMove doesn't take the latest value if we use a state instead of a ref
document.addEventListener('mousemove', handleMove);
if (onMoveStart) {
onMoveStart(e, movingRef.current, angle);
}
};
const handleMove = (e) => {
e.stopPropagation();
e.preventDefault();
if (!movingRef.current) {
return;
}
this.moveDOMElement(e);
};
I have something like this and I noticed if I replaced movingRef = useRef(false) with const [moving, setMoving] = useState(false), it doesn’t work. It works with refs and I read that useRef changes propagate faster since the callback function "handleMove" takes the cached value of the setState variable moving (or state), instead of taking the latest value, but if you use ref you will always use the latest value. Is this the case?
I heard that this is a closure-related behavior and using a state variable causes synchronization and side effect issues while using refs allows us to avoid that and get what we would expect.
2
Answers
Use
useRef
when the value has does not need the component to re-render. The.current
value of a ref is a variable that you control, updating it does not tell React to re-render.useState
is for values that should queue a re-render. When you call thesetX
returned byuseState
, React queues a re-render and the value will be the updated one on the next render. This is mentioned inuseState
‘s caveats:From the limited code you posted it looks like
movingRef
is not referenced in the template, updating it does not need a re-render, and souseRef
is a good choice.Yes, when you are using
useState
the set state is asynchronous. So it will not update the state immediately.useRef
gives you a mutable object. themovingRef
gives you the most recent value and can be updated directly.In your context, the
useState
may not update quickly for themousemove
event, so it’s better to useuseRef
since it’s mutable and not tied to the component’s render cycle.