Reputation: 5656
I saw this custom hook when reading some blog post
const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
};
I made a codesandbox to experiement with it https://codesandbox.io/s/weathered-surf-eenqo?file=/src/App.js
and indeed it works. It preserves the previous input value I had there.
And I tried to replicate this hook using useState
const usePrevious2 = (value) => {
const [prevValue, setPrevValue] = useState();
useEffect(() => {
setPrevValue(value);
}, [value]);
return prevValue;
};
However the value returned by usePrevious2
is in sync with the current state. I wonder what is the underline mechanism for the differences here? Why is that the ref
can preserver the previous state but not another useState
. Can someone explain this to me?
Upvotes: 0
Views: 45
Reputation: 371233
The issue with using useState
here is that state updates result in re-renders.
If you use usePrevious
/ useRef
and change the input, there will be one state update, when the input value changes - and after that state update occurs, the usePrevious
will shortly schedule a ref.current = value
assignment, but such assignment will not cause a re-render.
In contrast, with usePrevious2
/ useState
, when you use setPrevValue
, a re-render will occur. When the input field changes, there will be 2 re-renders; one when the input field changes, and then another after the useEffect
callback runs and calls setPrevValue
. So the usePrevious2
will only be "out of date" for a very short time, until its effect hook runs and sets the state again.
Upvotes: 1