React Hooks,如何在两个函数之间共享状态

React Hooks, how to share state between two functions

我来自 Vue 背景,当 HTML 被分成多个部分时,我很难理解如何有条件地显示某些内容。

假设我得到以下结构:

import React, { useState } from "react";
const [mobileNavOpen, setMobileNavOpen] = useState(false);

function Home() {
  return (
    <div>
      <button
        onClick={(): void => setMobileNavOpen(true)}
        type="button"
        className="btn"
      >
        X
      </button>
      {mobileNavOpen && <MobileNav />}
    </div>
  );
}

function MobileNav() {
  return (
    <div>
      <button
        onClick={(): void => setMobileNavOpen(false)}
        type="button"
        className="btn"
      >
        X
      </button>
    </div>
  );
}

export default Home;

我如何才能在 Home() 和 MobileNav() 中访问 [mobileNavOpen, setMobileNavOpen]。基本上我想要实现的是一个主页组件,用户可以在其中按下一个按钮,MobileMenu 组件在该按钮上打开,他们可以使用另一个按钮再次关闭菜单。

现在,从上数第 2 行 const [mobileNavOpen, setMobileNavOpen] = useState(false); 结果是 Error: Invalid hook call. Hooks can only be called inside of the body of a function component. 但我应该把它放在哪里?

这一行是否应该在 Home() 组件中,并且所有子组件都会发出一个事件来显示或关闭菜单?或者我需要一个状态管理库来处理这么简单的事情吗? "React" 的方法是什么?

一种简单的方法是将状态修饰符传递给子组件。为此,需要将钩子移动到父组件中。

import React, { useState } from "react";


function Home() {
  const [mobileNavOpen, setMobileNavOpen] = useState(false);
  return (
    <div>
      <button
        onClick={(): void => setMobileNavOpen(true)}
        type="button"
        className="btn"
      >
        X
      </button>
      {mobileNavOpen && <MobileNav setMobileNavOpen={setMobileNavOpen} />}
    </div>
  );
}

function MobileNav(setMobileNavOpen) {
  return (
    <div>
      <button
        onClick={(): void => setMobileNavOpen(false)}
        type="button"
        className="btn"
      >
        X
      </button>
    </div>
  );
}

export default Home;

或者,您可以对此进行一些抽象,以便您的子组件只定义所需的内容:

import React, { useState } from "react";

function Home() {
  const [mobileNavOpen, setMobileNavOpen] = useState(false);
  return (
    <div>
      <button
        onClick={(): void => setMobileNavOpen(true)}
        type="button"
        className="btn"
      >
        X
      </button>
      {mobileNavOpen && <MobileNav onClose={() => setMobileNavOpen(false)} />}
    </div>
  );
}

function MobileNav(onClose) {
  return (
    <div>
      <button
        onClick={(): void => onClose()}
        type="button"
        className="btn"
      >
        X
      </button>
    </div>
  );
}

export default Home;

docs 提供了一些管理共享状态的最佳实践。

import React, { useState } from "react";

function Home() {
  const [mobileNavOpen, setMobileNavOpen] = useState(false);
  return (
    <div>
      <button
        onClick={() => setMobileNavOpen(true)}
        type="button"
        className="btn"
      >
        X
      </button>
      {mobileNavOpen && <MobileNav setMobileNavOpen={setMobileNavOpen} />}
    </div>
  );
}

function MobileNav({setMobileNavOpen}) {
  return (
    <div>
      <button
        onClick={() => setMobileNavOpen(false)}
        type="button"
        className="btn"
      >
        X
      </button>
    </div>
  );
}

export default Home;
  1. 您必须将 useState 挂钩移至组件主体
  2. 将状态 setter 函数传递给您的子组件

Should this line be in the Home() Component and all child components emit an event to show or close the Menu?

是的。 然后将状态传递给 MobileNavComponent

如果您的 Home() Component 呈现 MobileNav() Component,您应该将 const [mobileNavOpen, setMobileNavOpen] = useState(false) 放入 Home(),例如:

const Home = () => {
   const [mobileNavOpen, setMobileNavOpen] = useState(false)

   return ( 
   <>
    ...
    <MobileNav 
      handleMobileNav={mobileNavOpen}
    />
    ...
   </>)
}

const MobileNav = ({ handleMobileNav }) => {

   return <></>
}