Little Code
Little Code

Reputation: 1545

Using hooks to manage display/hide of a menu

I am having a little trouble getting hooks to work in terms of managing the display/hide of a menu. My understanding is that the correct way to do this is to create a custom hook which is shared between components.

I have created my custom hook, and imported it on the relevant components, however the components do not seem to be reacting to a change in state (i.e. clicking on the open or close buttons has no effect).

I have created a minimal code example: https://codesandbox.io/s/nostalgic-taussig-67qvp

Upvotes: 0

Views: 686

Answers (1)

adel
adel

Reputation: 3507

of course your code will not work because custom hook are not shareable between component, you need to use context api or some global state manager like redux to achieve or you can do with passing props to the child like this:

parent Component :

import React,{useState,useEffect} from "react";
import MenuButton from "./MenuButton";
import MobileMenu from "./MobileMenu";
//import MobileMenu from "./menus/MobileMenu";
export default function Foobar() {
  const [isOpen,setIsOpen] = useState(false)
  const toggle = ()=>setIsOpen(current=>!current)
  return (
    <div>
      <MenuButton click={toggle} />
      <MobileMenu isOpen={isOpen} click={toggle} />
    </div>
  );
}

here will are setting shared state to both child by passing the state as props and the toogle function will be accessible from the it'S child.

for the menu Button Component :

import React from "react";

export default function MenuButton({click}) {
  return (
    <div id="menu-button-div" className="-mr-2 flex items-center md:hidden">
      <button
        type="button"
        onClick={click}
        className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out"
        id="main-menu"
        aria-label="Main menu"
        aria-haspopup="true"
      >
        <svg
          className="h-6 w-6"
          stroke="currentColor"
          fill="none"
          viewBox="0 0 24 24"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M4 6h16M4 12h16M4 18h16"
          />
        </svg>
        OPEN
      </button>
    </div>
  );
}

here the click props will fire the toggle function in the parent which will toggle state isOpen.

and for the menu Component:

import React  from "react";
import "./styles.css";
export default function MobileMenu({isOpen,click}) {
  return (
    <div id="mobile-menu-div" className={isOpen?"":"hidden"}>
      menu content
      <button
        type="button"
        onClick={click}
        className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out"
        aria-label="Close menu"
      >
        <svg
          className="h-6 w-6"
          stroke="currentColor"
          fill="none"
          viewBox="0 0 24 24"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M6 18L18 6M6 6l12 12"
          />
        </svg>
        CLOSE
      </button>
    </div>
  );
}

now the menu component will have access to the parent state isOpen passed as prop and you don't need to use useEffect to toggle the class jsx support in line javascript. well this it and you don't need custom hook to achieve this, hope this what your are looking for.

full working example.

Upvotes: 1

Related Questions