0

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>
  );
}

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your explanation it is way more clear now. However I am getting an error at line 3 saying that the property "getInitialState", _this is undefined. The terminal displays a warning that this is not allowed before super. Any idea on how to fix it? Thank you very much.
Oh yeah, I think you need a super() in your constructor before the call to this.getIntialState
You could just use what was provided by the question state = { isSwitchOn: false }, then omit the constructor. You currently call super without forwarding the props, which could lead to potential issues later. "Class components should always call the base constructor with props." - React State and Lifecycle
Thank you very much for your explanation, I will dedicate some time to methabolize the code, I think only at line 8 there's an edit but it is totally working. Thank you again Jason!
@3limin4t0r - He doesn't have any props to pass down though. If you included props, it would ask for prop definitions. If you have no props, you don't need to define props in your super.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.