I have parent ponent, which contains a global value in its state. Change of this value must trigger change of states of children ponents as in following example:
function Parent(props) {
const [parentState, setParentState] = useState(someState);
return (
<button onClick={() => setParentState(newState)>Button</button>
<ChildComponent parentState={parentState} />
}
function Child(props) {
const [childState, setChildState] = useState(getState(props.parentState));
}
Click on the button in this example should change trigger non-trivial change of the state in the Child ponent (which uses parentState as a parameter to generate its own state).
I guess the first answer to the problem would be to lift the state up - however I would like not to do that, because there are many Child generated through a .map function - I would need to retain their states in an array and propagate it to all the child ponents. The value in the parent ponent is a global value relevant for all the children and all the children must change their states when the parentState changes.
Is there any good way to achieve that without lifting the Child ponents' states? I hope I have described the problem well enough - if not I will be glad to update the information.
I have parent ponent, which contains a global value in its state. Change of this value must trigger change of states of children ponents as in following example:
function Parent(props) {
const [parentState, setParentState] = useState(someState);
return (
<button onClick={() => setParentState(newState)>Button</button>
<ChildComponent parentState={parentState} />
}
function Child(props) {
const [childState, setChildState] = useState(getState(props.parentState));
}
Click on the button in this example should change trigger non-trivial change of the state in the Child ponent (which uses parentState as a parameter to generate its own state).
I guess the first answer to the problem would be to lift the state up - however I would like not to do that, because there are many Child generated through a .map function - I would need to retain their states in an array and propagate it to all the child ponents. The value in the parent ponent is a global value relevant for all the children and all the children must change their states when the parentState changes.
Is there any good way to achieve that without lifting the Child ponents' states? I hope I have described the problem well enough - if not I will be glad to update the information.
Share Improve this question asked Feb 21, 2020 at 14:37 FaireFaire 1,0313 gold badges17 silver badges38 bronze badges 3- 1 Does this answer your question? React js change child ponent's state from parent ponent – Aurélien Foucault Commented Feb 21, 2020 at 14:39
-
Can you elaborate a bit on how the parent's global value is intended to be applied to the children? Do you apply the entire
parentState
to the children? If so, do the children even need their own states? I think your question implies that the parent sort of 'resets' the children on demand, but the children can then deviate and differ in state from the parent until the next 'reset' from the parent snaps the children back to being identical to the parent. Am I on the right track? – WGriffing Commented Feb 21, 2020 at 15:18 - Aurélien: I am already transferring parent's state to the children, problem is that in the children the state is set on initialization (see Child state) and not change on subsequent changes of parent's state. @WGriffing: The child loads an array of data dependent on parent's state (say user's global settings) and it's own, non-derivative state (ponent's setting). These two factors are passed as parameters of function that returns the data for the child. – Faire Commented Feb 24, 2020 at 7:19
3 Answers
Reset to default 4Based on your clarifying ment, here's some ideas on how to proceed. Depending on what a parentState
object contains, there might better ways to do this, but hopefully it will help spur some ideas.
- Use
parentState
in 2 ways.- As a
Child
prop. This will always be updated whenever theParent
changes its value. - As the initial value of one of the
Child
'suseState
hooks. This will initialize the child's derivative state, but will allow theChild
state to deviate over time based on user actions within theChild
ponent.
- As a
- Use
useEffect
hook(s) to trigger yourChild
getData function when theparentState
variable changes or when thechildStateSettings
variable changes. - Use multiple
useState
hooks inChild
to separate the non-derivative part of the state from the inherited/derivative part of theChild
's state. For the derivative state,childStateSettings
, useparentState
as the initial value.
So the Child
bees something like:
import { useEffect, useState } from 'react';
function Child(props) {
const { parentState } = props;
// initial value of child settings from parent
const [childStateSettings, setChildStateSettings] = useState(parentState);
// non-inherited/non-derivative state of child
const [childStateData, setChildStateData] = useState({});
// Depending on the number of settings and ways in which
// the user can make them different than the parent/global settings,
// you may want to have even more useState hooks to further separate
// the settings into individual pieces. I think this would simplify
// your various `onChange`/`onSelection'/etc. function logic, but I
// couldn't say for certain without more details.
useEffect(() => {
getData(childStateDerivative, childStateNonDerivative);
}, [parentState, childStateSettings]};
// pseudocode invented by me as a guess of
// how you might need to use things based on your ment
const getData = (parentState, childState) => {
// last spread object takes precedence if duplicate keys are present in both objects
const binedState = { ...parentState, ...childState };
API.get('http://some_path', binedState).then(data => {
setChildStateData(data);
});
};
// you'll probably draw some inputs so that the
// user can alter the child's state settings but
// I didn't bother trying to guess what that might look like.
return (<>...</>);
}
Child should not have a state of of it's own. It should pletely depend on parent state/props.
function Parent(props) {
const [parentState, setParentState] = useState(someState);
return (
<button onClick={() => setParentState(newState)>Button</button>
<ChildComponent parentState={parentState} />
}
function Child(props) {
}
When you change the parent state the child will redraw. You can use setState() in the constructor to modify your child state while it is being recreated in the DOM.