Reputation: 650
I have a parent component that has a state of its own and that is shared across the child components as well.
In my child component, I have a form and for the data, I've created a local state. Let's call this child component .
In my parent component, there is a button on click of which I update the data from my child's local state to my parent's state. This I do by passing a flag from parent to child.
Also my parent renders the same child twice making the final code like this:
const parent = () => {
const [parentState, setParentState] = useState(null);
const [submitSignal, setSubmitSignal] = useState(false);
const handleSave = () => {
setSubmitSignal(true);
}
return (
<div>
<div onClick={handleSave}>
Save Data
</div>
<Child
pos={0}
key={0}
parentState={parentState}
submitSignal={submitSignal}
setParentState={setParentState}
/>
<Child
pos={1}
key={1}
parentState={parentState}
submitSignal={submitSignal}
setParentState={setParentState}
/>
</div>
)
}
const Child = (props) => {
const [childState, setChildState] = useState(null);
React.useEffect(() => {
const { pos, submitSignal, parentState, setParentState } = props;
if (submitSignal) {
setParentState(...parentState, ...childState);
}
}, [props.submitSignal])
return (
<div>
// A large form which multiple fields
</div>
)
}
Now what's happening here is as soon as I make the submitSignal true from my parent component both the child receive it at the same time and try to update the parent's state. It's kind of a race condition situation where Child 0 updates the data but before it's even get updated in parent state Child 1 also updates the parent's state and thereby overwriting/removing what Child 0 added.
Please help me out with this.
P.S: The reason why I have gone with this structure is that in my Child I have a very large form and the same form is used twice.
Upvotes: 5
Views: 3046
Reputation: 5274
I see why you are confused, this is actually working exactly as intended.
before I continue: be aware:
for more details, read my article how-react-hooks-work. it will help you understand better functional components lifecycle and hooks.
about your specific issue: follow this code sandbox, it's just like your code with some logs.
there are no any racing conditions here, react doesn't care if 1000 children requested an update(via setstate for example) on the parent. because all the update request was on the same phase, only one render will be scheduled.
if you having a hard time understanding it, I would really recommend reading my article, how-react-hooks-work, which has simple to complicated examples that demonstrate these behaviors.
Upvotes: 0
Reputation: 323
Instead of setting the parent state directly, you have to use a callback function. this way, you will get updated previous state while overriding state.
if (submitSignal) {
setParentState((pstate)=>{
return {...pstate,...childstate}
});
}
https://stackoverflow.com/a/68531170/5707801
Upvotes: 1