在 Context API 和 Redux 之间做出选择

Irakli Tchigladze 2023年1月30日
  1. 在 React 中使用 Context API
  2. 在 React 中使用 React.createContext()
  3. 在 React 中使用 useContext() 钩子
  4. 在 React 中使用 Redux 库
  5. 何时使用 Context API 与 React 中的 Redux
在 Context API 和 Redux 之间做出选择

React 是最流行的 JavaScript 框架之一,因为它为 Web 应用程序创建了可重用的 UI 组件。它很容易与其他库集成,并提供了很大的灵活性。

React 应用程序通常具有一个父组件和多个子组件。将数据从父组件传递给子组件的默认方式称为 props

此功能对于组件的可重用性至关重要,组件是 React 应用程序的构建块。每个组件都接受执行特定操作所需的数据,并且可以拥有子组件并使用 props 传递数据。

如果你的 React 应用程序有一个简单的组件树,你可以使用 props 手动传递数据。然而,随着应用程序的增长,组件树变得更加复杂。

在某些时候,子组件将拥有自己的子组件。找到具有复杂组件层次结构的组件树并不少见。

在 React 中使用 Context API

复杂应用程序的组件树很难遍历。在这种情况下,通过树的每个分支手动传递 props 是不切实际的。

Context API 是一种将 props 从树顶部的父组件 传递到其子组件 的解决方案。

你可以使用 Context API、常规 propsRedux 来传递 props。关键是要知道每个人的优点并充分利用它们。

Context API 有助于在不同的树枝上传递大多数组件所需的特定 props。例如,在 React 应用程序的大多数组件中都需要诸如区域设置偏好之类的值。

从技术上讲,你可以使用 props 传递数据,但是导航组件树及其许多分支将花费太多时间。

相反,你可以使用 Context API 将数据从父组件直接传递给组件树较低级别的子组件。

让我们看一个简单的例子:

import "./styles.css";
import React from 'react'
import { useContext } from 'react'
const sampleContext = React.createContext()

export default function App() {
  return (
    <sampleContext.Provider value={10}>
    <div className="app">
      <Child></Child>
    </div>
    </sampleContext.Provider>
  );
}
function Child() {
  return (
    <div className="child">
      <Grandchild></Grandchild>
    </div>
  );
}
function Grandchild() {
  const value = useContext(sampleContext)
  return <div className="grandchild" style={{fontSize: 30}}>{value}</div>;
}

在这里,我们有三个组件:位于树顶部的 App 组件、Child 组件和 Grandchild 组件。

Grandchild 组件位于组件树的底部,可以直接访问父组件的 value 属性。prop 值不必手动通过每个树级别。

.createContext() API 带有核心 React 库,因此我们必须先导入它。然后我们创建一个 sampleContext 变量,它将存储 Context object

最后,我们从核心 React 库中导入 useContext() 钩子,我们将使用它从 Context API 中获取值。你可以查看实时 codesandbox

在 React 中使用 React.createContext()

React.createContext() 是返回 Context object 的主要方法。存储返回对象的变量应该在组件定义之外创建。

useEffect() 挂钩仅用于从 Context object 获取值,而不是创建它。React.createContext() 采用一个参数:Context object 的默认值。

如果子组件在其树中没有提供者,React 只会读取默认值。出于这个原因,React 开发人员经常使用默认值来隔离测试组件。

Context object 包含一个自定义 Provider 组件。它允许子组件订阅上下文对象中的值。

如果将 contextType 属性设置为上下文对象,你可以通过读取组件的 this.context 属性来访问 Provider 组件的值。

不幸的是,你只能订阅一个 Provider 组件。你可以为不同的上下文对象创建多个自定义提供程序组件。

这些可以嵌套在组件树中的各个级别。在这种情况下,子组件将读取最近的父组件的自定义 Provider 组件的值。

Provider 组件采用一个 value 属性,它可以分配一个你需要在子组件中访问的值。只要它的后代在组件树中,它就可以同时连接到多个孩子。

每次 Provider 组件的 value 属性发生变化时,所有订阅它的子组件都会重新渲染。通常,React 中的组件重新渲染由 .shouldComponentUpdate() 方法处理。

但是,此方法不处理使用来自 Provider 的值的子组件的更新。相反,子组件将先前的值与新的值进行比较并更新任何更改。

由于重新渲染不是由 .shouldComponentUpdate() 方法处理的,父组件的重新渲染不会自动重新渲染子组件。

在 React 中使用 useContext() 钩子

有多种方法可以使用 Context 对象中的值。

首先,你可以设置类组件的 contextType 属性。它必须设置为上下文对象。

访问该值的第二种方法是使用 Context.Consumer 自定义组件。此自定义组件的子组件必须是适合功能组件的函数。

然而,订阅 Provider 组件的最简单方法是使用 useContext() 挂钩。正如你在上面的实际示例中所见,它接受一个参数,并且它必须是一个上下文对象。

这样,你可以访问 Provider 组件的 value 属性并将其存储在变量中。让我们再看一个例子:

function Grandchild() {
  const value = useContext(sampleContext)
  return <div className="grandchild" style={{fontSize: 30}}>{value}</div>;
}

value 变量存储来自自定义 Provider 组件的值。为了更好地演示,请查看 codesandbox

在 React 中使用 Redux 库

Redux 是一个用于管理复杂 React 应用程序状态的库。它与 React 是分开的,由不同的团队开发。

Redux 是最受欢迎的库,是 Context API 的可行替代方案,也是具有丰富功能的更高级库。它可以替代 Context API。但是,Context API 并不具备 Redux 的所有功能。

Context APIRedux 库都可以将数据传递到树下部的组件。与 Context API 不同,Redux 带有 Redux DevTools

Redux DevTools 可以让你跟踪你的状态更新。Redux 还允许你使用 middleware 和许多其他 Context API 不可用的高级功能。

何时使用 Context API 与 React 中的 Redux

如果这是你使用 Redux 的主要动机,你不需要 Redux 将数据共享给子组件而无需手动传递 props

如果你考虑改用 Context API,那将是最好的。它具有更简单的界面,并且更易于设置。

如果使用 middleware 对使你的 React 应用程序正常工作至关重要,那么 Redux 会更好。Redux 还附带了额外的库,例如 redux-persist 用于在本地存储数据。

要获取有关 Redux 高级功能的更多信息,请查看此博客

Irakli Tchigladze avatar Irakli Tchigladze avatar

Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.

LinkedIn