I want to have a child component reference and update a state; however, when I try to do so, it only works once or twice before breaking. Strangely, the parent element can still update the state.
import React, { useEffect, useState } from "react";
export default function RegistrationPopup() {
const [advancedMode, setAdvancedMode] = useState(false);
const [currentPage, setCurrentPage] = useState(null);
// The child function that tries to call setAdvancedMode
const child = (
<div>
<button
onClick={() => {
setAdvancedMode(!advancedMode);
}}
>
set advanced mode child
</button>
</div>
);
// Set the current page to the child
useEffect(() => {
setCurrentPage(child);
}, []);
// Return the parent component, which references the child
return (
<div>
{"mode is: " + (advancedMode ? "advanced" : "normal")}
<br />
<button
onClick={() => {
setAdvancedMode(!advancedMode);
}}
>
set advanced mode parent
</button>
{currentPage}
</div>
);
}
Even though the parent and child elements both call setAdvancedMode(!advancedMode)
, only the parent element actually updates the state. The child element will not trigger a state change, as shown in this sandbox:
https://codesandbox.io/p/sandbox/holy-monad-wlw4gq?file=%2Fsrc%2FApp.js
1
Separate out your child component and pass setAdvancedMode as props
https://codesandbox.io/p/sandbox/sad-sanderson-7rk34k?file=%2Fsrc%2FApp.js%3A2%2C1
import React, { useState, useEffect } from "react";
const ChildComponent = ({ advancedMode, setAdvancedMode }) => (
<div>
<button
onClick={() => {
setAdvancedMode(!advancedMode);
}}
>
set advanced mode child
</button>
</div>
);
export default function RegistrationPopup() {
const [advancedMode, setAdvancedMode] = useState(false);
const [currentPage, setCurrentPage] = useState(null);
useEffect(() => {
setCurrentPage(
<ChildComponent advancedMode={advancedMode} setAdvancedMode={setAdvancedMode} />
);
}, [advancedMode]); // Re-create the child component when advancedMode changes
return (
<div>
{"mode is: " + (advancedMode ? "advanced" : "normal")}
<br />
<button
onClick={() => {
setAdvancedMode(!advancedMode);
}}
>
set advanced mode parent
</button>
{currentPage}
</div>
);
}
``