简体   繁体   中英

Using React Hooks in in an IIFE breaks rules of hooks

Background

I'm working on a sidebar component that can be opened from many buttons in the UI. I want to 1) only render it once, 2) grant access to update its isVisible state to these buttons without drilling props down through a common ancestor.

Expectations vs Reality

I'd expect that I could create a context with its own api method to update an internal state. In my code sample I'm attempting to do this with an IIFE.

Questions

  1. How does this break the rules of hooks?
  2. How else can I provide an update function to this context?
export const SidebarContext = createContext((() => {
  const [isVisible, setIsVisible] = useState(false)

  return {
    isVisible,
    toggleVisibility: () => setIsVisible(!isVisible)
  }
})())

createContext() receives the default value. So you're defining a function which is invoked immediately and the result of it will be used as default value for the context. That's where the useState breaks this rule :

Call Hooks from React function components.

In order to accomplish what you want you can do this:

import React, { createContext, useContext, useState } from "react";

const SidebarContext = createContext();

function Provider({ children }) {

  let [isVisible, setIsVisible] = useState(false);
  let toggle = useCallback(() => setIsVisible(s => !s), [setIsVisible])

  // Pass the `state` and `functions` to the context value
  return (
    <SidebarContext.Provider value={{ isVisible, toggle }}>
      {children}
    </SidebarContext.Provider>
  );
}

function YourButton() {
  let { isVisible, toggle } = useContext(SidebarContext);
  return (
    <div>
      <div>Sidebar is {isVisible : 'open': 'close'}</div>
      <button onClick={toggle}>
        Toggle
      </button>
    </div>
  );
}

function App() {
  return (
    <Provider>
      <YourButton />
    </Provider>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM