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.