Search code examples
reactjsinfinite-loopuse-effectuse-state

Sync two state without infinite loop in React


How can I keep two related values synced, as the code bellow shows, without generating an infinite loop?

If use the setter of value1 = 3, I want to update value2 = '3'.

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

const [value1, setValue1] = useState(1);
const [value2, setValue2] = useState('1');

useEffect(() => {
  setValue2(`${value1}`);
}, [value1]);

useEffect(() => {
  setValue1(parseInt(value2));
}, [value2]);

useEffect(() => {
  setValue1(3);
}, []);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


Solution

  • Don't use two stateful values - instead, only use one stateful value, and convert the type when needed:

    const [value1, setValue1] = useState(1);
    const value2 = String(value1);
    

    This same sort of technique can be used anywhere in React where you have one variable whose value can be completely determined from the current value of another - have one stateful variable, the source of truth, and calculate the second variable when you need to.

    Just for argument's sake, a different approach that would work would be to combine both into a single object:

    const [values, setValues] = useState({
      num: 1,
      str: '1'
    });
    

    and then to update them, call setValues a single time to update them in tandem - but the first method is probably easier in most circumstances.