我有一个react应用程序,我在其中构建了一个简单的菜单,可以在单击时更改状态以打开和关闭它.这与同一组件中的菜单按钮一起工作得很好.然而,我现在希望能够从另一个组件打开菜单,在本例中是从开始页英雄打开菜单.

我有两个组件:header.js和hero.js

我试图做的是当我按下英雄上的按钮时打开菜单.

我try 导入组件、动作和状态,但没有任何效果.我知道我做错了,但我不知道如何解决它,也找不到任何解决方案,尽管我确信有一个.

这是我的代码示例.

header.js

import React, { useState } from 'react';

export default function Header() {
  const [isOpen, setIsOpen] = useState(false);

  const menuToggle = event => {
    setIsOpen(current => !current);
  };

  return (
    <header className={`header ${isOpen ? "open" : "closed"}`}>
      <button onClick={menuToggle}>Toggle menu</button>
    </header>
  );
}

hero.js

import setIsOpen from '../header/Header';

export default function Hero() {
  const menuToggle = event => {
    setIsOpen(true);
  };

  return (
    <section className="hero">
      <button onClick={menuToggle}>Toggle menu</button>
    </section>
  );
}

推荐答案

解决方案是将isOpen个状态提升到公共祖先组件,并将状态和更新器/回调作为props 向下传递到适当的组件.

基本的琐碎例子:

报头

export default function 报头({ isOpen, menuToggle }) {
  return (
    <header className={["header", isOpen ? "open" : "closed"].join(" ")}>
      <button onClick={menuToggle}>Toggle menu</button>
    </header>
  );
}

英雄

export default function 英雄({ menuToggle }) {
  return (
    <section className="hero">
      <button onClick={menuToggle}>Toggle menu</button>
    </section>
  );
}
const ParentComponent = () => {
  const [isOpen, setIsOpen] = React.useState(false);

  const menuToggle = event => {
    setIsOpen(open => !open);
  };

  return (
    <>
      <报头 isOpen={isOpen} menuToggle={menuToggle} />
      <英雄 menuToggle={menuToggle} />
    </>
  );
};

If there isn't a direct parent-child relationship between these components then you can either pass the props through all intermediate components until you get to both 报头 and 英雄, or you can implement a React Context to provide the value and avoid the props drilling issue.

示例:

export const MenuContext = React.createContext({
  isOpen: false,
  menuToggle: () => {},
});

export const useMenuContext = () => React.useContext(MenuContext);

const MenuContextProvider = ({ children }) => {
  const [isOpen, setIsOpen] = React.useState(false);

  const menuToggle = event => {
    setIsOpen(open => !open);
  };

  return (
    <MenuContext.Provider value={{ isOpen, menuToggle }}>
      {children}
    </MenuContext.Provider>
  );
};

export default MenuContextProvider;

MenuContextProvider渲染为公共祖先组件,下游使用useMenuContext来访问上下文值,无论组件在哪里.

App

const App = () => {
  ...

  return (
    <MenuContextProvider>
      ... 
      ... 报头 somewhere down the ReactTree ...
      ... 英雄 somewhere down the ReactTree ...
      ...
    </MenuContextProvider>
  );
};

报头

export default function 报头() {
  const { isOpen, menuToggle } = useMenuContext();

  return (
    <header className={["header", isOpen ? "open" : "closed"].join(" ")}>
      <button onClick={menuToggle}>Toggle menu</button>
    </header>
  );
}

英雄

export default function 英雄() {
  const { menuToggle } = useMenuContext();

  return (
    <section className="hero">
      <button onClick={menuToggle}>Toggle menu</button>
    </section>
  );
}

更多详情请参见:

Reactjs相关问答推荐

使用筛选器的Primereact DataTable服务器端分页?

在React Create App TS项目中安装material UI

无法将react 路由状态从路由传递给子组件

React:关于useEffect钩子如何工作的困惑

react 挂钩-使用有效澄清

为什么查询错误在处理后仍出现在控制台中?RTK查询+ React

如何使我的代码可以接受我想要的每一个链接

如何在物料界面react 的多选菜单中设置最大 Select 数限制

React,当我调用handleSubmit()函数时,我正在将application/json和multiform/data中的数据发送到后端,但student_image中没有数据:null

在 React 中,如何在指向同一组件的路由中拥有未定义数量的多个动态路径段?

无法通过 fetch 获取数据到上下文中

MERN,将动态列表中的元素插入数组

在reduce()方法上得到NaN

数据表格组件需要所有行都具有唯一的ID属性.或者,您可以使用getRowId属性.

useEffect内部的RETURN语句在首次按钮点击事件中似乎无效的原因是什么?

如何在我的自定义主题中样式化MUI TreeItem组件

如何将 DocuSign 控制台界面嵌入到 React 应用中

父状态改变后子组件丢失状态

如何在自定义 JSX 元素上声明属性?

由于另一个子组件,如何在react 中渲染另一个子组件