React way to open a NavBar onClick on a button

Viewed 7459

I trying to find a way to open the navbar of ReactJS app when i'm clicking on my "MENU" button.

At the beginning my nav component have a width of 0px (with overflow : hidden). When i'm clicking on the button my nav should have a width of 400px. I'm a beginner with React.

I have two React Components :

  1. Topbar
export default function Topbar() {
    return (
        <div className="topbar__container">
            <div className='topbar__menuButton'>
                <Link className="topbar__link">MENU</Link>
            </div>
            <div className="topbar__title">
                <Link to="/" className="topbar__link">EDGAR</Link>
            </div>
        </div>
    )
}
  1. Nav
const Nav = () => {
    return (
        <div className="navbar__container">
                <Query query={CATEGORIES_QUERY} id={null}>
                    {({ data: { categories } }) => {
                        return (
                            <nav className="nav">
                                <ul>
                                    {categories.map((category, i) => {
                                        return (
                                            <li key={category.id}>
                                                <Link to={`/category/${category.id}`} className="nav__link">
                                                    {category.name}
                                                </Link>
                                            </li>
                                        )
                                    })}
                                </ul>
                            </nav>
                        )
                    }}
                </Query>
            </div>
    )
}

export default Nav
2 Answers

To achieve something like that you have to set this logic in the common parent of both component (here App for the example).

App will manage a state to determine if the Nav is open or not. The state is called isMenuOpen and can be changed using the setIsMenuOpen() function. We will give to the children Nav the state isMenuOpen and to the children TopBar a callback from the function setIsMenuOpen():

App.jsx

import React from "react";

import TopBar from "./TopBar";
import Nav from "./Nav";

export default function App() {
  const [isMenuOpen, setIsMenuOpen] = React.useState(false);

  return (
    <div className="App">
      <TopBar setMenuStatus={setIsMenuOpen} />
      <Nav isOpen={isMenuOpen} />
    </div>
  );
}


Then the TopBar have to set the value of isMenuOpen to true using the function setIsMenuOpen() from the props.

TopBar.jsx

import React from "react";

export default function Topbar({ setMenuStatus }) {
  return (
    <div className="topbar__container">
      <div className="topbar__menuButton">
        <button
          type="button"
          onClick={() => {
            setMenuStatus(true);
          }}
        >
          Menu
        </button>
      </div>
    </div>
  );
}


Then the component Nav will set a specific class (here .open) if isOpen coming from props is true.

Nav.jsx

import React from "react";
import "./styles.css";

export default function Nav({ isOpen }) {
  return (
    <div id="nav" className={isOpen ? "open" : ""}>
      Menu
    </div>
  );
}

styles.css

#nav {
  display: none;
}

#nav.open {
  height: 400px;
  display: inline-block;
}

You can try this example in this codesandbox.

import React, {useState} from "react";
import "./styles.css";

export default function App() {
  const [toggle, setToggle]= React.useState(false)
  const [width, setWidth]= React.useState('')

  const showMenu = () => {
    setToggle(!toggle)
    if(toggle === true) {
      setWidth('50px')
    }else {
      setWidth('500px')
    }
  }
  return (
    <div className="App">
      <button onClick={showMenu}>Menu</button>
      <div style={{width, border:'1px solid red'}}>
        <li>text</li>
        <li>text</li>
        <li>text</li>
        <li>text</li>
      </div>
    </div>
  );
}
reproducing link: https://codesandbox.io/s/billowing-flower-rxdk3?file=/src/App.js:0-592

Related