Joji
Joji

Reputation: 5656

React: confusion about the usage of `useRef` here for storing the previous state

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

Answers (1)

CertainPerformance
CertainPerformance

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

Related Questions