Home > Software design >  Why does useState cause this simple code to behave incorrectly?
Why does useState cause this simple code to behave incorrectly?

Time:02-14

I have written a simple component to reproduce the problem I am having in a much larger project component.

Say I have an arrayA where I'd like to continuously add the value 1 on every button click and a state arrayB I would like to update on the button click.

export default function UseStateTest(props) {
  const arrayA = [];
  const [arrayB, setArrayB] = useState([1, 2]);

  function handleClick() {
    arrayA.push(1);
    setArrayB([3, 4]);
    console.log(arrayA);
  }

  return <button onClick={handleClick}>Test</button>;
}

With the setArrayB there, the code behaves incorrectly and when I click the button: arrayA will always have 1 element 1 (I think, from experience in my other code where I'm having a similar problem, that the code is actually replacing the element instead of pushing).

When I comment the setArrayB out, the code behaves correctly, with a new element '1' being added to the array on every button click.

Please may someone help me understand what is causing this behaviour.

CodePudding user response:

Your component function is called each time your component needs to be re-rendered. You get a different arrayA on each call to your component (as with any other function). That's why there's a useState hook (and some others, like useRef): So you can persist stateful information across renders.

Without the call to setArrayB, your component doesn't change its state, so React doesn't re-render it (doesn't call your function again). With the call to setArrayB, you're changing the component's state, causing a re-render, which does a new call, which creates a new arrayA (and a new handleClick).

You can't store any information that should persist between renders in simple variables/constants within the function, since those are recreated on each function call. Instead, use useState (for state information that, when changed, should cause your component to re-render), useRef (for stateful information that shouldn't cause your component to re-render [rare]), and various other hooks.

  • Related