Apologies in advance if this is a newbie question, but I’m struggling with passing a state variable down to a child component if I’m using a router.
I’m using ionic 7 and capacitor android 5.1.1
"dependencies": {
"@capacitor/android": "5.1.1",
"@capacitor/app": "5.0.5",
"@capacitor/core": "5.1.1",
"@capacitor/haptics": "5.0.5",
"@capacitor/keyboard": "5.0.5",
"@capacitor/status-bar": "5.0.5",
"@ionic/react": "^7.0.0",
"@ionic/react-router": "^7.0.0",
"@transistorsoft/capacitor-background-fetch": "^5.0.0",
"@transistorsoft/capacitor-background-geolocation": "^5.0.0",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"axios": "^1.4.0",
"ionicons": "^7.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4"
}
Problem: I am building an app which contains multiple pages but I need them to all share a global state and I want updates whenever that state changes. My simplified solution has a boolean state variable in App, and a child component which uses and can update this state variable (via a callback)
App:
setupIonicReact();
const App: React.FC = () => {
console.log('App: Rendering App');
const [booleanValue, setBooleanValue] = useState(false);
console.log('App:BooleanValue', booleanValue);
const handleToggle = () => {
console.log('App: handleToggle');
setBooleanValue((prevValue) => !prevValue);
};
return (
<IonApp>
<ChildComponent booleanValue={booleanValue} onToggle={handleToggle} />
</IonApp>
)
};
export default App;
Child Component:
interface ChildComponentProps {
booleanValue: boolean;
onToggle: () => void;
}
const ChildComponent: React.FC<ChildComponentProps> = ({ booleanValue, onToggle }) => {
console.log('ChildComponent: Rendering ChildComponent with booleanValue: ', booleanValue);
return (
<IonPage>
<div>
<p>Boolean Value: {booleanValue.toString()}</p>
<button onClick={onToggle}>Toggle</button>
</div>
</IonPage>
);
};
export default ChildComponent;
This works fine and my output when clicking the button is as desired:
Now, as I want multiple pages which can update this state I build in a router:
const App: React.FC = () => {
console.log('App: Rendering App');
const [booleanValue, setBooleanValue] = useState(false);
console.log('App:BooleanValue', booleanValue);
const handleToggle = () => {
console.log('App: handleToggle');
setBooleanValue((prevValue) => !prevValue);
};
return (
<IonApp>
<IonReactRouter>
<IonRouterOutlet>
<Route path="/OperativePage">
<ChildComponent booleanValue={booleanValue} onToggle={handleToggle} />
</Route>
<Redirect to="/OperativePage" />
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
)
};
export default App;
Now my state is not getting updated in the child page (the child page is not getting re-rendered):
My third test was to use the render method, which does cause the re-render of the child page, but does not change the state in the child:
setupIonicReact();
const App: React.FC = () => {
console.log('App: Rendering App');
const [booleanValue, setBooleanValue] = useState(false);
console.log('App:BooleanValue', booleanValue);
const handleToggle = () => {
console.log('App: handleToggle');
setBooleanValue((prevValue) => !prevValue);
};
return (
<IonApp>
<IonReactRouter>
<IonRouterOutlet>
<Route path="/OperativePage"
render={(routeProps) => (
<ChildComponent
booleanValue={booleanValue}
onToggle={handleToggle}
{...routeProps}
/>
)}
/>
<Redirect to="/OperativePage" />
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
)
};
export default App;
Can anyone explain what I’m doing wrong here and the reason for the different behaviours when attempting to use the router?
Thanks