If i'm calling two state updater functions in an onClick event handler, and the second state updater function uses the state, updated by the first state updater function, than the second state updates by the previous or default value of the first state. How can I update two states that depend on each other in an event handler?
For example, when pressing the button element, we'll see 2 in the p element instead of 11. Only after the second press, it will show 11.
export default function Stage() {
const [a, setA] = React.useState(1);
const [b, setB] = React.useState(1);
function updateA(x) {
setA(x);
};
function updateB() {
setB(1 a);
};
return (
<div>
<button onClick={() => {updateA(10); updateB()}}></button>
<p>{b}</p>
</div>
)
};
CodePudding user response:
When your states in a component depend each other this is an antipattern (Don't Sync State), try to avoid it and redesign a component.
Instead minimaze state and derive from it:
export default function Stage() {
const [a, setA] = React.useState(1);
function updateA(a) {
setA(10);
};
function updateB(x) {
return a x
};
return (
<div>
<button onClick={() => {updateA(1)}></button>
<p>{updateB(1)}</p>
</div>
)
};
P.S. setState is async operation and in your example line updateA(1); updateB(1) is assumed to work sync
CodePudding user response:
if you want to update a state after another call the second setState inside a useEffect.
here is a solution for your problem codepen demo
function App() {
const aInitialValue = 1;
const [a, setA] = React.useState(aInitialValue);
const [b, setB] = React.useState(1);
function updateA() {
setA(10);
}
function updateB(x) {
setB(x a);
}
React.useEffect(() => {
if (a !== aInitialValue) {
updateB(1);
}
}, [a]);
return (
<div>
<button
onClick={() => {
updateA(1);
}}
></button>
<p>{b}</p>
</div>
);
}
CodePudding user response:
utilize the lifecycle hook useEffect to create sideEffects when A updates to then set your B state.
export default function Stage() {
const [a, setA] = React.useState(1);
const [b, setB] = React.useState(1);
function updateA(x) {
setA(x);
};
useEffect(() => {
function updateB() {
setB(1 a);
};
},[a])
return (
<div>
<button onClick={() => updateA(10)></button>
<p>{b}</p>
</div>
)
};