Tuesday, 12 October 2021

Is it a common practice in React to keep the same value in state and ref?

My React app uses setTimeout() and setInterval(). Inside them, I need to access the state value. As we know, closures are bound to their context once created, so using state values in setTimeout() / setInterval() won't use the newest value.

Let's keep things simple and say my component is defined as such:

import { useState, useEffect, useRef } from 'react';

const Foo = () => {
    const [number, setNumber] = useState(0);
    const numberRef = useRef(number);

    // Is this common? Any pitfalls? Can it be done better?
    numberRef.current = number;

    useEffect(
        () => setInterval(
            () => {
                if (numberRef.current % 2 === 0) {
                    console.log('Yay!');
                }
            },
            1000
        ),
        []
    );

    return (
        <>
            <button type="button" onClick={() => setNumber(n => n + 1)}>
                Add one
            </button>
            <div>Number: {number}</div>
        </>
    );
};

In total I came up with 3 ideas how to achieve this, is any of them a recognized pattern?

  1. Assigning state value to ref on every render, just like above:

    numberRef.current = number;
    

    The benefit is very simplistic code.

  2. Using useEffect() to register changes of number:

    useEffect(
        () => numberRef.current = number,
        [number]
    );
    

    This one looks more React-ish, but is it really necessary? Doesn't it actually downgrade the performance when a simple assignment from point #1 could be used?

  3. Using custom setter:

    const [number, setNumberState] = useState(0);
    const numberRef = useRef(number);
    
    const setNumber = value => {
        setNumberState(value);
        numberRef.current = value;
    };
    

Is having the same value in the state and the ref a common pattern with React? And is any of these 3 ways more popular than others for any reason? What are the alternatives?



from Is it a common practice in React to keep the same value in state and ref?

No comments:

Post a Comment