negomi / react-burger-menu

:hamburger: An off-canvas sidebar component with a collection of effects and styles using CSS transitions and SVG path animations
http://negomi.github.io/react-burger-menu/
MIT License
5.05k stars 586 forks source link

Example using hooks, context, and controlling open state programmatically #308

Closed klittle32 closed 5 years ago

klittle32 commented 5 years ago

First off, thanks for publishing and maintaining such a great component.

As a React noob, I wanted to learn more about the new hooks apis in React and decided to attempt refactoring the example in the faq that demonstrates how to programmatically control the open state to use function components instead of a class.

To do so, I ended up using the useState hook, the useContext hook, and the context api in React.

Here is my example in case anyone finds it helpful.

import React, { useState, useContext } from 'react'
import {slide as Menu} from 'react-burger-menu'

// make a new context
const MyContext = React.createContext();

// create the provider
const MyProvider = (props) => {
  const [menuOpenState, setMenuOpenState] = useState(false)

  return (
    <MyContext.Provider value={{
      isMenuOpen: menuOpenState,
      toggleMenu: () => setMenuOpenState(!menuOpenState),
      stateChangeHandler: (newState) => setMenuOpenState(newState.isOpen)
    }}>
      {props.children}
    </MyContext.Provider>
  )
}

// create a button that calls a context function to set a new open state when clicked
const Button = () => {
  const ctx = useContext(MyContext)
  return (
    <button onClick={ctx.toggleMenu}>Toggle menu</button>
  )
}

// create a navigation component that wraps the burger menu
const Navigation = () => {
  const ctx = useContext(MyContext)

  return (
    <Menu 
      customBurgerIcon={false}
      isOpen={ctx.isMenuOpen}
      onStateChange={(state) => ctx.stateChangeHandler(state)}
    />
  )
}

// default export here
const App = () => {
  return (
    <MyProvider>
      <div>
        <Button />
        <Navigation />
      </div>
    </MyProvider>
  )
}

export default App;
johngrasty commented 5 years ago

@klittle32 Thanks for this. I had figured out all of it, except for the onStateChange section. This really saved me some time!

negomi commented 5 years ago

Thanks so much @klittle32, I've added your example to the FAQs too: https://github.com/negomi/react-burger-menu/wiki/FAQ#i-want-to-control-the-open-state-programmatically-but-i-dont-understand-how-to-use-the-isopen-prop

okabamac commented 5 years ago

Hi, what does the 'stateChangeHandler' actually do? Thanks a lot for this! I had no issue implementing according to my use case but I am a bit confused about what that handler does.

negomi commented 5 years ago

Hey @okabamac,

In the example, stateChangeHandler is just a pass-through function, which is used as the onStateChange callback. All it does is call setMenuOpenState, which updates the value of menuOpenState.

Hope that helps!