在 React 中使用 Context

在 React 中,有时候组件间需要共享一些数据,这些数据可能会存在嵌套多层的关系中。一种常见的解决方案是通过 props 将数据从祖先组件传递给后代组件。但是,如果孙子、曾孙等后代组件需要访问这些数据,可能也需要一层层地将数据传递下去,这样就显得很麻烦。

为了解决这个问题,React 提供了 Context API。在 React 中,Context 允许我们将数据沿着组件树传递下去,不必显式地将数据层层传递给每个组件。

创建 Context

我们可以使用 React.createContext 方法来创建一个 Context 对象。

const MyContext = React.createContext(defaultValue);

这里的 defaultValue 是一个可选的值,表示当没有任何一个祖先组件提供了相应的 Context 时,该组件会使用 defaultValue 做为默认值。这个默认值也可以通过 Providervalue 属性来覆盖。

使用 Context

使用 Context 的两种方式:

  • Consumer:用于在函数式组件中使用 Context。
  • useContext:在函数式组件中使用 Context,使用 Hooks。

Consumer

在类似于以下的组件树中,我们需要将 username 数据从 User 组件传递到 Welcome 组件。

创建 Context

首先,我们需要创建一个 Context:

const UserContext = React.createContext("Guest");

这里的 defaultValue 是一个字符串 "Guest"。

提供 Context

接下来,在 User 组件中,我们需要将 username 提供给 UserContext.Provider

<Header />
<UserContext.Provider value={this.state.username}>
  <Welcome />
</UserContext.Provider>

这里我们使用 this.state.username 作为 value,因为 User 组件中有一个叫做 username 的 state。

消费 Context

最后,在 Welcome 组件中,我们可以通过 UserContext.Consumer 来消费 UserContext 中的 username

function Welcome() {
  return (
    <UserContext.Consumer>
      {username => (
        <h2>Welcome, {username}!</h2>
      )}
    </UserContext.Consumer>
  );
}

useContext

使用 useContext,我们可以更简洁地在函数式组件中使用 Context。

const username = useContext(UserContext);

上述代码中,username 获得了 UserContext 中的数据。需要注意的是,useContext 必须在函数式组件中使用。

共享多个数据

如果需要共享多个数据,在 Provider 中传入一个包含所有数据的对象即可。

<UserContext.Provider value={{username: this.state.username, theme: this.state.theme}}>
  <Welcome />
</UserContext.Provider>

ConsumeruseContext 中,可以像下面这样使用多个数据:

const { username, theme } = useContext(UserContext);

示例代码

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

const UserContext = createContext("Guest");
const ThemeContext = createContext("light");

function App() {
  const [username, setUsername] = useState("John");
  const [theme, setTheme] = useState("light");

  return (
    <div>
      <UserContext.Provider value={username}>
        <ThemeContext.Provider value={theme}>
          <Header />
          <Welcome />
        </ThemeContext.Provider>
      </UserContext.Provider>
      <button onClick={() => setUsername("Jane")}>Change User</button>
      <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>Toggle Theme</button>
    </div>
  );
}

function Header() {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <header style={{ backgroundColor: theme }}>
          <h1>My App</h1>
        </header>
      )}
    </ThemeContext.Consumer>
  );
}

function Welcome() {
  const username = useContext(UserContext);
  const theme = useContext(ThemeContext);

  return (
    <div style={{ backgroundColor: theme }}>
      <h2>Welcome, {username}!</h2>
    </div>
  );
}

总结

使用 Context 可以帮助我们在 React 中共享数据,特别是当数据需要沿组件树传递时。通过创建 Context 和在 Provider 中提供数据,可以在 Consumer 或 useContext 中访问数据。Context 的 API 是 React 提供的,使用上比较方便,但需要注意一些细节。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b4a6c3add4f0e0ffd89442