Reputation:
I am trying to understand basic React web design practices, but I haven't found a proper explanation on how to toggle classes also to the parent components. In vanilla JS would have been easier by adding an Event Handler to the document.
I have a button
inside the MobileMenu
component which upon click, shows the menu and changes its appearance. I would like to toggle a class also to the div
wrapper of my Home
function in order to move from left the body when opening the menu. I read that it can be done by setting the state in the parent component and pass a function from the child to the parent component but I'm getting only errors and I'm unable to find a proper example. This is my current working code which only toggles the classes inside the component. Thank you in advance for any explanation.
MobileMenu component:
class MobileMenu extends React.Component {
state = {
isSwitchOn: false,
}
render() {
console.log(this.state.isSwitchOn)
const isOn = this.state.isSwitchOn;
return (
<div className="mobileNavigation">
<div className="btnMenuContainer">
<button className={isOn ? "hamburger is-active" : "hamburger "}
onClick={() => this.setState({ isSwitchOn: !isOn })} type="button">
</button>
</div>
<div className={isOn ? "mobileNavContainer showMobileNav" : "mobileNavContainer" }>
</div>
</div>
);
}
}
export default MobileMenu
Home Function:
export default function Home({ children }) {
return (
<div>
<Global />
<MobileMenu />
<SectionHero>
<h1>Title</h1>
<p>Paragraph</p>
</SectionHero>
</div>
);
}
Upvotes: 0
Views: 994
Reputation: 562
If you want the parent to be able to switch classes based on the state, then the parent needs to hold the state (state should go at the top most level in which it is needed and then flow downwards as props). Then the parent needs to pass the state and the onChange function down to the child so that it can use it to call the parent function and update the state, like so:
home class:
class Home extends React.Component {
constructor() {
super();
this.state = this.getInitialState();
}
getInitialState() {
return {
isSwitchOn: false
}
}
handleOnClick = () => {
this.setState({isSwitchedOn: !this.state.isSwitchedOn});
};
render() {
cosnt {isSwitchedOn} = this.state; //<-- Now that you have in state on the parent, you can use it here in the parent to do what ever logic you need to do with it.
return (
<div className={isSwitchedOn ? "someClass" : "someOtherClass"} >
<Global />
<MobileMenu
isSwitchedOn={isSwitchedOn}
onClick={this.handleOnClick}
/>
<SectionHero>
<h1>Title</h1>
<p>Paragraph</p>
</SectionHero>
</div>
);
}
}
Mobile Menu function:
export default function MobileMenu({isSwitchedOn, onClick}) {
return (
<div className="mobileNavigation">
<div className="btnMenuContainer">
<button className={"hamburger" + (isSwitchedOn ? " is-active" : "")}
onClick={onClick} type="button" />
</div>
<div className={"mobileNavContainer" + (isSwitchedOn ? " showMobileNav" : "")} />
</div>
);
}
Also, in your Mobile menu you can simplify your className logic for your button and DIV, as they both have a constant that is always on.
Upvotes: 1