状态不随 useContext 改变

state do not change with useContext

你好

我正在尝试进行菜单切换,其中我有一个初始值为 false 的变量,使用 react createContext 和 useContext 挂钩,我将初始状态设置为 true

// useMenu Context
import React, { useContext, useState } from 'react'

export const useToggle = (initialState) => {
  const [isToggled, setToggle] = useState(initialState)
  const toggle = () => setToggle((prevState) => !prevState)
  // return [isToggled, toggle];
  return { isToggled, setToggle, toggle }
}

const initialState = {
  isMenuOpen: true,
  toggle: () => {},
}

export const MenuContext = React.createContext(initialState)

const MenuProvider = ({ children }) => {
  const { isToggled, setToggle, toggle } = useToggle(false)
  const closeMenu = () => setToggle(false)
  return (
    <MenuContext.Provider
      value={{
        isMenuOpen: isToggled,
        toggleMenu: toggle,
        closeMenu,
      }}>
      {children}
    </MenuContext.Provider>
  )
}
export default MenuProvider

export const useMenu = () => {
  return useContext(MenuContext)
}

so 如果为 true 它将显示菜单 如果为 false 它将显示 Div 其中有 div

App.js

const { isMenuOpen } = useMenu()

//the providder
<MenuProvider>
  <Header mode={theme} modeFunc={toggleTheme}/>
      {isMenuOpen ? (
         <Menu />
      ) : (
      <Switch>
        <Route path='/writing' component={Writings} />
        <Route path='/meta' component={Meta} />
        <Route path='/contact' component={Contact} />
        <Route path='/project' component={Project} />
        <Route exact path='/' component={Home} />
        <Route path='*' component={NotFound} />
      </Switch>
    )}
  <Footer />{' '}
</MenuProvider>

当我添加一个 onclick 事件时,菜单的 NavLink 按钮关闭它它不起作用

菜单


const { closeMenu } = useMenu()
// return statement
{paths.map((item, i) => {
  return (
    <MenuItem
      key={i}
      link={item.location}
      svg={item.icon}
      path={item.name}
      command={item.command}
      onClick={closeMenu}
     />
  )
})}

我哪里错了

问题

我怀疑问题出在 App 那里你有一个 useMenu 挂钩 之外 MenuProvider 使用 App。此 useMenu 挂钩使用 MenuContext 上下文,但在没有提供程序的情况下,它会使用默认的初始上下文值。

const initialState = {
  isMenuOpen: true,
  toggle: () => {},
};

export const MenuContext = React.createContext(initialState);

export const useMenu = () => {
  return useContext(MenuContext)
};

React.createContext

const MyContext = React.createContext(defaultValue);

Creates a Context object. When React renders a component that subscribes to this Context object it will read the current context value from the closest matching Provider above it in the tree.

The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This default value can be helpful for testing components in isolation without wrapping them.

解决方案

因为我怀疑你想要 run/provide 多个菜单提供者我相信解决方案是将 MenuProvider 移出并包装 App 以提供你正在更新的上下文嵌套组件。

App.jsx

const { isMenuOpen } = useMenu();

...

<>
  <Header mode={theme} modeFunc={toggleTheme}/>
  {isMenuOpen ? (
    <Menu />
  ) : (
    <Switch>
      <Route path='/writing' component={Writings} />
      <Route path='/meta' component={Meta} />
      <Route path='/contact' component={Contact} />
      <Route path='/project' component={Project} />
      <Route exact path='/' component={Home} />
      <Route path='*' component={NotFound} />
    </Switch>
  )}
  <Footer />
</>

index.jsx (?)

import App from './App.jsx';

...

//the provider
<MenuProvider>
  <App />
</MenuProvider>