Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

React.js – Wait for updated state

I have a parent component (Parent). This component (hook) has a state variable called refs. This variable is an object, which saves all refs used in Parent component and all Child components like this way:

const [refs, setRefs] = useState({
    "ref1": ref1,
    "ref2": ref2,
    "ref3": ref3,
});

Please don’t ask why. Actually this is needed in the current solution.

So the code of the Parent component is like this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

export default function Parent(props) {
    
    const ref1 = useRef(null);
    const ref2 = useRef(null);
    const ref3 = useRef(null);

    const [refs, setRefs] = useState({
        "ref1": ref1,
        "ref2": ref2,
        "ref3": ref3,
    });

    useEffect(() => {
        updateRefs({
            "ref1": ref1,
            "ref2": ref2,
            "ref3": ref3,
        });
    },[
        ref1,
        ref2,
        ref3
    ])

    function updateRefs(updateRefs) {
        let updatedRefs = Object.assign({}, refs, updateRefs);
        setRefs(updatedRefs);
    }

    return (
        <div>
            <Child1
                updateRefs={updateRefs}
            />
            <Child2
                updateRefs={updateRefs}
            />
        </div>
    )
}

In this example the Parent component has 3 refs. These are saved directly during the initialization of the variable refs as shown above. When they are assigned to a DOM element, the useEffect is being called to update them.

Now to my issue.
Now the Childs are returning their refs by calling the function updateRefs.

This becomes a problem, when I have more than 1 Child in my Parent component.
Let’s say Child1 is returning ref4 and ref5, while Child2 is returning ref6 and ref7.
When the Parent component is rendering, Child1 is returning its refs. So before the update of Child1, the state of refs is still containing ref1, ref2 and ref3. After the update, it should also contain ref4 and ref5.

Now when Child2 is returning its refs, the state is still unchanged despite the update of Child1 (= ref1, ref2 and ref3).
So Child2 is now calling updateRefs, but without the previous update of Child1.
In the end, the state will be

ref1: ref1,
ref2: ref2,
ref3: ref3,
ref6: ref6,
ref7: ref7

instead of having all Child updateRefs:

ref1: ref1,
ref2: ref2,
ref3: ref3,
ref4: ref4,
ref5: ref5,
ref6: ref6,
ref7: ref7

Is there a way to "wait" for the updated state from Child1 and then do the updates of Child2?

>Solution :

This relies on the state of refs at the time this function was defined:

let updatedRefs = Object.assign({}, refs, updateRefs);
setRefs(updatedRefs);

So if both child components invoke this same instance of updateRefs then they’re both using the same instance of refs. This creates a race condition and whoever submits their update last wins.

State updates are queued/batched, and you can use the state setter callback to make use of the state value at that point in the queue/batch rather than the state value that was available when this function was defined.

For example:

setRefs(prev => {
  let updatedRefs = Object.assign({}, prev, updateRefs);
  return updatedRefs;
});

That way the second queued/batched state update (the previous "winner" of the race condition) would be using the value prev, which would include changes from the first queued/batched state update as well.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading