Home > Software design >  Understanding useRef and useEffect in this general example
Understanding useRef and useEffect in this general example

Time:04-14

So I am trying to understand useRef properly but there is one thing I am unable to wrap my head around. See this basic example

function App() {
    const [counter, setCounter] = useState(0);
    const previousCountRef = useRef(null);

    useEffect(() => {
        previousCountRef.current = counter
    },[counter]) 

    return(
        <>
        <h1>{counter}</h1>
        {previousCountRef.current !== null && (<h5>Prev: 
        {previousCountRef.current}</h5>)}  // check if previous is not null

    <button onClick={() => setCounter(counter   1)}>CLICKME</button>
    )
    </>

}

So in this example, we increment the counter by 1 if we press the button. our useEffect only updates if we change the value of counter. Our ref variable is able to store the value of counter before it is changed.

That is the part that confuses me. How is the useEffect able to store the value of the previous counter? If we click the button, the counter is updated. Because the counter is updated, useEffect can run and gets set equal to the value of counter. How is the ref variable 1 step behind?

On initial render, the counter variable changes from null to 0 so it runs useEffect in that situation as well, thereby setting prevCountRef.current = 0 too. They are in sync.

CodePudding user response:

I think the answer is two parts:

  1. useEffect runs after the render. So this code previousCountRef.current = counter runs after the setCounter has completed and the component has re-rendered.
  2. Updating refs does not cause re-renders. So the code previousCountRef.current = counter does not trigger a re-render for you to see the new value in your JSX.

This leads to the ref printing one step behind, even though its actual current value may have already been updated to match the state.

  • Related