如何使用React Context(附代码示例)

406 阅读4分钟

React Context是一个强大的功能。如果你的React应用程序的规模增长超过了一个小的应用程序,给它一个尝试是没有错的。许多第三方库,如Redux,都在引擎盖下使用它,所以为什么不学习一下呢。

特别是当你的组件层次结构在垂直方向上增长时,将几个React组件传递下去会变得很乏味--从一个父组件到一个深度嵌套的子组件。大多数情况下,中间的所有React组件对这些道具不感兴趣,只是将道具传递给下一个子组件,直到它到达所需的子组件。

本教程给你一个使用React Context的简单用例的演练。

React Context为什么

你还记得上次你不得不在你的组件树下传递道具的时候吗?在React中,你经常会遇到这个问题,它被称为 "道具钻孔"。

     +----------------+
          |                |
          |        A       |
          |        |Props  |
          |        v       |
          |                |
          +--------+-------+
                   |
         +---------+-----------+
         |                     |
         |                     |
+--------+-------+    +--------+-------+
|                |    |                |
|                |    |        +       |
|       B        |    |        |Props  |
|                |    |        v       |
|                |    |                |
+----------------+    +--------+-------+
                               |
                      +--------+-------+
                      |                |
                      |        +       |
                      |        |Props  |
                      |        v       |
                      |                |
                      +--------+-------+
                               |
                      +--------+-------+
                      |                |
                      |        +       |
                      |        |Props  |
                      |        C       |
                      |                |
                      +----------------+

反过来,这也会使每一个必须传递这些道具而不使用它们的组件变得混乱。React Context给了你一个摆脱这种混乱的方法。你可以通过React Context以隐式方式道具传递给这些组件,而不是通过每个组件传递道具。如果一个组件需要访问上下文中的信息,它可以按需消费,因为一个顶级组件在上下文中提供了这些信息。

     +----------------+
          |                |
          |       A        |
          |                |
          |     Provide    |
          |     Context    |
          +--------+-------+
                   |
         +---------+-----------+
         |                     |
         |                     |
+--------+-------+    +--------+-------+
|                |    |                |
|                |    |                |
|       B        |    |        D       |
|                |    |                |
|                |    |                |
+----------------+    +--------+-------+
                               |
                      +--------+-------+
                      |                |
                      |                |
                      |        E       |
                      |                |
                      |                |
                      +--------+-------+
                               |
                      +--------+-------+
                      |                |
                      |        C       |
                      |                |
                      |     Consume    |
                      |     Context    |
                      +----------------+

**React Context的用例是什么?**例如,设想你的React应用程序有一个颜色集的主题。在你的应用程序中,有各种组件需要了解该主题来设计自己的风格。因此,在你的顶层组件中,你可以让下面所有的React子组件都能访问这个主题。这就是React的Context发挥作用的地方。

 +----------------+
          |                |
          |       A        |
          |                |
          |     Provide    |
          |       Theme    |
          +--------+-------+
                   |
         +---------+-----------+
         |                     |
         |                     |
+--------+-------+    +--------+-------+
|                |    |                |
|                |    |                |
|       B        |    |        D       |
|                |    |                |
|                |    |                |
+----------------+    +--------+-------+
                               |
                      +--------+-------+
                      |                |
                      |                |
                      |        E       |
                      |                |
                      |                |
                      +--------+-------+
                               |
                      +--------+-------+
                      |                |
                      |        C       |
                      |                |
                      |     Consume    |
                      |       Theme    |
                      +----------------+

**谁提供/使用React Context?**React组件A--我们的顶级组件--提供上下文,React组件C--作为子组件之一--消费上下文。不过,介于两者之间的是组件D和E。由于D和E组件并不关心这些信息,所以它们不消费上下文。只有组件C消耗它。如果组件A下面的任何其他组件想要访问上下文,它可以消费它。

React Context如何使用

首先,你必须创建React Context本身,它可以让你访问一个提供者和消费者组件。当你通过使用createContext ,用React创建上下文时,你可以给它传递一个初始值。初始值也可以是空的。

// src/ThemeContext.js
import React from 'react';
const ThemeContext = React.createContext(null);
export default ThemeContext;

其次,组件A将不得不为上下文提供给定的提供者组件。在这种情况下,它的value ,但它可以是任何东西,从组件的状态(如取来的数据)到道具。如果该值来自一个可修改的React状态,那么传递给提供者组件的值也可以改变。

// src/ComponentA.js

import React from 'react';
import ThemeContext from './ThemeContext';

const A = () => (
  <ThemeContext.Provider value="green">
    <D />
  </ThemeContext.Provider>
);

组件A只显示组件D,虽然没有传递任何道具给它,但却让下面所有的React组件都能使用这个值green 。其中的一个子组件将是最终消耗上下文的组件C。

第三,在你的组件C中,在组件D下面,你可以消耗上下文对象。注意,组件A不需要通过组件D在props中传递任何东西,以便它到达组件C。

// src/ComponentC.js

import React from 'react';
import ThemeContext from './ThemeContext';

const C = () => (
  <ThemeContext.Consumer>
    {value => (
      <p style={{ color: value }}>
        Hello World
      </p>
    )}
  </ThemeContext.Consumer>
);

组件可以通过消耗上下文来获得其风格。消费者组件通过使用一个渲染道具使传递的上下文可用。你可以想象,按照这种方式,每个需要根据主题进行样式设计的组件都可以通过使用ThemeContext的Consumer组件从React的Context获得必要的信息。你只需要使用提供者组件,在他们上面的某个地方传递一次值。

React Context什么时候

你什么时候应该使用React Context?一般来说,有两种情况下要使用它:

  • 当你的React组件层次结构垂直增长时,你希望能够将道具传递给子组件而不影响中间的组件。在整个React Context教程中,我们都以这个用例为例。
  • 当你想在React中使用React Hooks进行高级状态管理,通过React Context在你的React应用中传递状态和状态更新函数。通过React Context做到这一点,你就可以创建一个共享的全局状态。

一个使用React Context的运行中的应用程序可以在这个GitHub仓库中找到。毕竟,React Context是一种向深度嵌套的React组件传递道具的好方法,因为它不会打扰中间的组件。