I tried to make the simplest example of this here. When you check the box, the parent text Text #1 alternates back and forth from "true" to "false" while the child text Text #2 never changes. I want Text #2 to change just like Text #1 does.
function Parent(props) {
const [state1, setState1] = useState(true);
const [currentView, setCurrentView] = useState(<Child checkHandler={checkHandler} state1={state1} />);
function checkHandler(event) {
setState1(event.target.checked);
}
return (
<div>
Text #1: {state1 ? "true" : "false"}
{currentView}
</div>
);
}
export default Parent;
function Child({
state1,
checkHandler
}) {
return (
<div>
Text #2: {state1 ? "true" : "false"}
<form>
<input type="checkbox" id="checkbox" onChange={checkHandler} />
<label for="checkbox">Check</label>
</form>
</div>
);
}
export default Child;
I've searched for similar answers, but I can't find anywhere a simple explanation on how to do what I think would be a very fundamental thing to do in React Redux.
CodePudding user response:
Component instances should almost never be put into state, because then their props and own state won't update naturally. You need to be calling <Child checkHandler={checkHandler} state1={state1} /
whenever the parent re-renders so that when the parent values change, the child can re-render with its new props.
The checkbox is also not checked by default, yet you do const [state1, setState1] = React.useState(true);
- better to be consistent. Consider adding the checked
prop to the child.
function Parent(props) {
const [state1, setState1] = React.useState(true);
function checkHandler(event) {
setState1(event.target.checked);
}
return (
<div>
Text #1: {state1 ? "true" : "false"}
<Child checkHandler={checkHandler} state1={state1} />
</div>
);
}
function Child({
state1,
checkHandler
}) {
return (
<div>
Text #2: {state1 ? "true" : "false"}
<form>
<input type="checkbox" id="checkbox" onChange={checkHandler} checked={state1} />
<label htmlFor="checkbox">Check</label>
</form>
</div>
);
}
ReactDOM.createRoot(document.querySelector('.react')).render(<Parent />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>
CodePudding user response:
No need to put the entire component into the state -- it won't work either. Just give the state variable as a prop to the child.
function Parent(props) {
const [state1, setState1] = useState(true);
function checkHandler(event) {
setState1(event.target.checked);
}
return (
<div>
Text #1: {state1 ? "true" : "false"}
<Child checkHandler={checkHandler} state1={state1} />
</div>
);
}
export default Parent;
function Child({ state1, checkHandler }) {
return (
<div>
Text #2: {state1 ? "true" : "false"}
<form>
<input type="checkbox" id="checkbox" onChange={checkHandler} />
<label for="checkbox">Check</label>
</form>
</div>
);
}
export default Child;