React

Context Hooks - useContext

这篇文章将介绍React中的useContext Hook,一个强大的工具用于简化跨组件状态共享。我们将解析其工作原理、基本用法及最佳实践,以帮助读者在React项目中有效应用useContext,提高代码质量和可维护性。
This entry is part 4 of the seriesenjoy-react-hooks

React程序中传递数据的主要方式是通过props传递,就像火车网络一样,props允许我们在整个应用程序中传递状态和其它数据。

但随着应用程序复杂度的提升,不同组件之间的数据传递经常需要通过多层嵌套的props传递,这不仅使得代码结构变得复杂,而且难以维护。为了解决这个问题,React提供了第二种传递数据的方式: Context上下文

Context有点像特快列车。它允许我们”跳过“某些站点,并直接从一个组件跳到另一个组件。

在这篇文章中我们将学习有关它的一切。

The Problem

在React应用程序中,有时候我们会遇到这样的情况:在顶层组件(例如App)中定义了一些数据(比如用户信息user),并且这些数据需要被多个深层次的子组件(如ProfileHeader)所共享。在这种情况下, 我们首先想到的就是通过逐级传递props的方式来实现。

上述流程的真实代码如下:

随着React应用程序的发展,组件结构可能变得越来越复杂,尤其是在大型项目中,不同组件之间共享状态或数据的需求也随之增加。传统的逐级传递props的方式在处理简单的数据流时尚可行,但当组件层级加深时,这种方法往往会导致代码冗余和难以维护的问题。开发者们不得不在多个中间组件(例如: Dashboard)中添加额外的props,即使这些组件本身并不直接使用这些数据,只是为了将它们传递给更深层次的子组件。

为了解决这一问题,React引入了Context上下文机制。Context提供了一种在组件树中高效传递数据的方式,无论组件层级有多深,都可以轻松访问到这些数据,而无需通过中间组件的props进行逐级传递。这种机制极大地简化了数据管理,使得代码更加整洁,也降低了维护成本。

Syntax

接着上面的案例,让我们使用Context上下文来替换逐级透穿props

Step 1: Context

首先,我们需要创建一个新的Context,这个Context将用来存储和分发user信息。

Context可以被视为一个频道,一个我们可以用来向应用程序内部广播数据的无线电频率。它是我们用来传递数据的载体。

Step 2: Provider

App组件中,我们使用UserContext.Provider来包裹Dashboard组件,并通过value属性传入user对象。这意味着Dashboard及其所有子组件现在都可以访问到user信息。

Step 3: Consumer

DashboardHeaderProfile等组件中,我们可以使用useContext Hook来直接访问user信息,而不需要从props中获取。

完整代码如下:

通过采用这种方式,我们可以有效地避免在组件树中重复传递user对象,同时保持代码的整洁和易于维护。

最佳实践

组织代码

  • Context逻辑提取到Provider Component中,
    • user 相关上下文提取到UserProvider
    • theme相关上下文提取到ThemeProvider
  • Provider Component中返回useContext的自定义版本
    • UserProvider中返回useUserContext
    • ThemeProvider中返回useThemeContext
  • Consumer中直接使用自定义hook

优化后的代码如下:

性能优化

在上一篇文章中,我们学习了如何使用React.memo创建纯组件。一个纯组件只会在 propsstate 发生变化时才会重新渲染。

但是,当一个纯组件消费了Context会发生什么呢?比如:

使用React.memo包装Profile得到了一个纯组件,这个组件在什么情况下会重新渲染呢?

本质上来说,你可以把Context理解为internal props,它和普通的props没有任何区别,当Context中的value发生变化时,消费了这个上下文值的组件也会重新渲染。

它在功能上等同于:

因此,为避免消费了ContextConsumner组件无效渲染,可以:

  • 使用React.useMemoContextvalue进行缓存。
  • 使用React.memo包装Consumner,使其成为纯组件。

Questions? Let's chat

discord logoOPEN DISCORD
6423
members online
previous article
Permormance Hooks - useMemo & useCallback
next article
Ref Hooks - useRef & useImperativeHandle

A TypeScript Full Stack Blog

Share articles about Typescript, React, Next.js, Node.js and Css from time to time.
No spam, unsubscribe at any time.