在前面的章节中,我们学习了最基本的 Hook,例如 State Hook、Reducer Hook 和 Effect Hook。我们使用这些 Hook 开发了一个小型博客应用程序。在博客应用程序的开发过程中我们注意到,我们必须将 user
状态从 App
组件传递到 UserBar
组件,从 UserBar
组件传递 Login
、Register
和 Logout
组件。为了避免像这样传递状态,我们现在将学习 React Context 和 Context Hook。
在本章中,我们将从学习 React Context 是什么,以及 provider 和 consumer 是什么开始。然后,我们将使用 Context Hooks 作为 Context consumer,并讨论何时应该使用 Context。最后,我们将通过 Context 实现主题和全局状态。
本章将介绍以下主题:
- 引入 React context 作为传递 props 的替代方案
- 通过 context 实现主题
- 使用全局状态的 context
技术要求
应该已经安装了相当新版本的 Node.js(vl1.l2.0 或更高版本)。还需要安装 Node.js 的 npm 包管理器。
本章的代码可以在 GitHub 存储库中找到:https://github.com/PacktPublishing/Learn-React-Hooks/tree/master/Chapter05。
观看以下视频,了解代码的实际应用:
请注意,强烈建议您自己编写代码。不要简单地运行已提供的代码示例。重要的是你自己编写代码,以便你能够正确学习和理解。但是,如果遇到任何问题,始终可以参考代码示例。
现在,让我们从本章开始。
介绍 React Context
在前面的章节中,我们将 user 状态和 dispatch
函数从 App
组件传递给了 UserBar
组件;然后从 UserBar
组件转到 Logout
、 Login
和 Register
组件。React Context 为这种在多个级别的组件上传递 props 的繁琐方式提供了一种解决方案,它允许我们在组件之间共享值,而不必通过 props 显式传递它们。正如我们将要看到的,React Context 非常适合在整个应用程序中共享值。
首先,我们将仔细研究 props 的传递问题。然后,我们将引入 React Context 作为问题的解决方案。
传递 Props
在深入学习 React Context 之前,让我们回顾一下我们在前面章节中实现的内容,以便了解 context 解决的问题:
- 在
src/App.js
中,我们定义了 user 状态和dispatch
函数:
const [ state, dispatch ] = useReducer(appReducer, { user: '', posts: defaultPosts })
const { user, posts } = state
- 然后,我们将 user 状态和
dispatch
函数传递给UserBar
组件(和CreatePost
组件):
return (
<div style={{ padding: 8 }}>
<UserBar user={user} dispatch={dispatch} />
{user && <CreatePost
user={user}
posts={posts}
dispatch={dispatch}
/>}
<hr />
<PostList posts={posts} />
</div>
)
- 在
src/user/UserBar.js
组件中,我们将 user 状态作为 prop,然后将其传递给Logout
组件。我们还将dispatch
函数作为一个 prop,并将其传递给Logout
、Login
和Register
组件:
export default function UserBar({ user, dispatch }) {
if (user) {
return <Logout user={user} dispatch={dispatch} />
} else {
return (
<React.Fragment>
<Login dispatch={dispatch} />
<Register dispatch={dispatch} />
</React.Fragment>
)
}
}
- 最后,我们在
Logout
、Login
和Register
组件中使用了dispatch
和user
属性。
React Context 允许我们跳过步骤 2 和 3,直接从步骤 l 跳到步骤 4。可以想象,对于更大的应用程序,Context 变得更加有用,因为我们可能不得不在许多级别上传递 props。
介绍 React Context
React Context 用于在 React 组件树中共享值。通常,我们希望共享全局值,例如 user 状态和 dispatch
函数、应用程序的主题或所选语言。
React Context 由两部分组成:
- provider,提供(设置)值
- consumer,消费(使用)值
我们将首先使用一个简单的示例来了解 context 的工作原理,在下一节中,我们将在我们的博客应用程序中实现它们。我们也使用 create-react-app 创建了一个新项目。在我们的简单示例中,我们将定义一个主题 context,其中包含应用程序的主要颜色。
定义 Context
首先,我们必须定义 context。自引入 Hook 以来,这种工作方式一直没有改变。
我们只需使用 React.createContext(defaultValue)
函数来创建一个新的 context 对象。我们将默认值设置为 { primaryColor: 'deepskyblue' }
,因此当未定义 provider 时,我们的主要颜色默认为 deepskyblue
。
在 src/App.js
中,在 App
函数之前添加以下定义:
export const ThemeContext = React.createContext({ primaryColor: 'deepskyblue' })
请注意我们如何在此处导出 ThemeContext,因为我们需要为 consumer 导入它。
这就是我们使用 React 定义 context 所需要做的一切。现在我们只需要定义 consumer。
定义 Consumer
现在,我们必须在 Header
组件中定义 consumer 。我们现在将以传统方式执行此操作,在接下来的步骤中,使用 Hook 来定义 consumer:
- 创建新的
src/Header.js
文件 - 首先,我们必须从 App.js 文件中导入
ThemeContext
:
import React from 'react'
import { ThemeContext } from './App'
- 现在,我们可以定义组件,其中我们使用
ThemeContext.Consumer
组件和一个render
函数作为children
prop,以便使用 context 值:
const Header = ({ text }) => (
<Themecontext.consumer>
{theme => (
- 在
render
函数中,我们现在可以使用 context 值来设置Header
组件的color
样式:
<h1 style={{ color: theme.primarycolor }}>{text}</h1>
)}
</ThemeContext.Consumer>
)
export default Header
- 现在,我们仍然需要通过添加以下
import
语句在src/App.js
中导入Header
组件:
import Header from './Header'
- 然后,我们将当前的
App
函数替换为以下代码:
const App = () => (
<Header text="Hello World" />
)
export default App
使用这样的 context 是有效的,但是,正如我们在第一章中学到的,以这种方式使用带有 render
函数 props 的组件会使我们的 UI 树混乱,并使我们的应用程序更难调试和维护。
使用 Hook
使用 context 的更好方法是使用 useContext
Hook!这样,我们可以像使用任何其他值一样使用 context 值,其方式与 useState
Hook 类似:
- 编辑
src/Header.js
。首先,我们从 React 导入useContext
Hook,从 src/App 导入ThemeContext
对象:
import React, { useContext } from 'react'
import { Themecontext } from './App'
- 然后,我们创建 Header 组件,现在我们在其中定义
useContext
Hook:
const Header = ({ text }) => {
const theme = useContext(Themecontext)
- 我们组件的其余部分将与以前相同,只是现在我们可以简单地返回我们的
Header
组件,而无需为 consumer 使用额外的组件:
return <h1 style={{ color: theme.primarycolor }}>{text}</h1>
}
export default Header
正如我们所看到的, Hook 的使用让我们的 context consumer 代码更加简洁。此外,它将更易于阅读、维护和调试。
我们可以看到标题现在的颜色是深天蓝:
使用 Context Hook 的简单应用程序
如我们所见,我们的主题 context 成功地为标题提供了主题。
定义 Provider
context 使用传递给 React.createContext
的默认值,当没有定义 provider 时。这对于调试未嵌入到应用程序中的组件非常有用。例如,我们可以将单个组件作为独立组件进行调试。在应用程序中,我们通常希望使用 provider 来提供 context 的值,我们现在将定义该值。
编辑 src/App.js
,在 App
函数中,我们简单地将 Header
组件与 <ThemeContext.Provider>
组件包装在一起,其中我们将 coral
作为 primaryColor
传递:
const App = () => (
<Themecontext.Provider value={{ primarycolor: 'coral' }}>
<Header text="Hello World" />
</Themecontext.Provider>
)
export default App
现在我们可以看到标题颜色从深天蓝色变为珊瑚色:
Provider 更改了标题颜色
如果我们想更改 context 的值,我们可以简单地调整传递给 Provider
组件的 value
属性。
请注意,当我们定义一个 provider 而不将value
prop 传递给它时,不会使用 context 的默认值!如果我们定义一个没有value
prop 的 provider,那么 context 的值将是未定义的。
现在我们已经为 context 定义了单个 provider,让我们继续定义多个嵌套的 provider。
嵌套 Provider
使用 React Context,还可以为同一个 context 定义多个 provider。使用此技术,我们可以覆盖应用程序某些部分中的 context 值。让我们考虑前面的示例,并给它添加第二个页眉:
- 编辑
src/App.js
,并添加第二个Header
组件:
const App = () => (
<ThemeContext.Provider value={{ primaryColor: 'coral' }}>
<Header text="Hello World" />
<Header text="This is a test" />
</ThemeContext.Provider>
)
export default App
- 现在,使用不同的
primaryColor
定义第二个Provider
组件:
const App = () => (
<ThemeContext.Provider value={{ primaryColor: 'coral' }}>
<Header text="Hello World" />
<Themecontext.Provider value={{ primarycolor: 'deepskyblue' }}>
<Header text="This is a test" />
</Themecontext.Provider>
</ThemeContext.Provider>
)
export default App
如果我们在浏览器中打开应用程序,现在第二个标题的颜色与第一个标题的不同:
使用嵌套 Provider 重写 context 值
如我们所见,我们可以通过定义 provider 来覆盖 React Context 值。provider 也可以嵌套,因此可以覆盖组件树中较高位置的其他 provider 的值。
示例代码
小型主题 context 示例的示例代码可以在 Chapter05/chapter5_1
文件夹中找到。
只需运行 npm install
即可安装所有依赖项,运行 npm start
启动应用程序,然后在您的浏览器中访问 http://localhost:3000
(如果它没有自动打开)。
Context 的替代方案
但是,我们应该小心,不要太频繁地使用 React Context,因为它会使重用组件变得更加困难。只有当我们需要访问许多组件中的数据,这些组件处于不同的嵌套级别时才应该使用 context。此外,我们需要确保只对不经常更改的数据使用 context。频繁更改 context 的值可能会导致整个组件树重新渲染,从而导致性能问题。这就是为什么对于频繁变化的值,我们应该改用状态管理解决方案,比如 Redux 或 MobX。
如果我们只想避免传递 props,我们可以传递渲染的组件而不是数据。例如,假设我们有一个 Page
组件,它渲染一个 Header
组件,Header
组件渲染一个 Profile
组件,Profile
组件它渲染一个Avatar
组件。我们得到一个传递给 Page
组件的 headerSize
属性,我们在 Header
组件中需要它,但在 Avatar
组件中也需要它。与其通过多个级别传递 props,我们可以执行以下操作:
function Page ({ headerSize }) {
const profile = (
<Profile>
<Avatar size={headerSize} />
</Profile>
)
return <Header size={headerSize} profile={profile} />
}
现在,只有 Page 组件需要知道 headerSize
属性,并且不需要在树中进一步传递它。在这种情况下,context 不是必需的。
这种模式称为 控制反转,它可以使您的代码比传递 props 或使用 context 更干净。但是,我们也不应该总是使用这种模式,因为它会使更高级别的组件更加复杂。
实现主题
在一个小示例中学习如何实现主题之后,我们现在将使用 React Context 和 Hook 在我们的博客应用程序中实现主题。
定义 Context
首先,我们必须定义 context。在我们的博客应用程序中,我们将为 context 创建一个单独的文件,而不是在 src/App.js
文件中定义它。为 context 使用单独的文件可以更轻松地在以后维护它们。此外,我们始终知道从哪里导入 context,因为从文件名中可以清楚地看出。
让我们开始定义一个主题 context:
- 创建一个新的
src/contexts.js
文件。 - 然后,我们导入
React
:
import React from 'react'
- 接下来,我们定义
ThemeContext
。与之前的小示例中一样,我们将默认的primaryColor
设置为deepskyblue
。此外,我们将secondaryColor
设置为coral
:
export const ThemeContext = React.createContext({
primaryColor: 'deepskyblue',
secondaryColor: 'coral'
})
现在我们已经定义了 context,我们可以继续定义 Context Hook。
定义 Context Hook
定义 context 后,我们将使用 Context Hook 定义我们的 consumer。首先为 Header 创建一个新组件,然后为现有的 Post
组件定义一个 Context Hook。
创建 Header 组件
首先,我们创建一个新的 Header
组件,它将用我们应用程序的 primaryColor
色显示 React Hooks Blog
。
现在让我们创建 Header
组件:
- 创建一个新的
src/Header.js
文件。 - 在这个文件中,我们导入了
React
,以及useContext
Hook:
import React, { useContext } from 'react'
- 接下来,我们从之前创建的
src/contexts.js
文件中导入ThemeContext
:
import { ThemeContext } from ''./contexts'
- 然后,我们定义
Header
组件和 Context Hook。我们没有将 context 值存储在theme
变量中,而是使用解构来直接提取primaryColor
值:
const Header = ({ text }) => {
const { primaryColor } = useContext(ThemeContext)
- 最后,我们返回 h1 元素,就像我们之前在我们的小示例中所做的那样,并
export
Header
组件:
return <h1 style={{ color: primaryColor }}>{text}</h1>
}
export default Header
现在我们的 Header
组件已经定义,我们可以使用它了。
使用 Header 组件
创建 Header
组件后,我们将在 App
组件中使用它,如下所示:
- 编辑
src/App.js
,并导入 Header 组件:
import Header from './Header'
- 然后,在
UserBar
组件之前渲染Header
组件:
return (
<div style={{ padding: 8 }}>
<Header text="React Hooks Blog" />
<UserBar user={user} dispatch={dispatch} />
您可能希望将React Hooks Blog
值重构为传递给App
组件(应用程序配置)的 prop,因为我们已经在此组件中使用它三次。
现在,我们的 Header
组件将在应用程序中渲染,我们可以继续在 Post
组件中实现 Context Hook。
实现 Post 组件的 Context Hook
接下来,我们要以次要颜色显示文章标题。为此,我们需要为 Post
组件定义一个 Context Hook,如下所示:
- 编辑
src/post/Post.js
,并调整import
语句以导入useContext
Hook:
import React, { useContext } from 'react'
- 接下来,我们导入
ThemeContext
:
import { ThemeContext } from '../contexts'
- 然后,我们在
Post
组件中定义一个 Context Hook,并通过解构从主题中获取secondaryColor
值:
export default function Post ({ title, content, author }) {
const { secondarycolor } = useContext(Themecontext)
- 最后,我们使用
secondaryColor
值来设置h3
元素的样式:
return (
<div>
<h3 style={{ color: secondarycolor }}>{title}</h3>
如果我们现在查看我们的应用程序,我们可以看到来自 ThemeContext
的两种颜色都被正确地使用:
我们的 ThemeContext 实战
正如我们所看到的,我们的应用程序现在给主标题使用主要颜色,给文章标题使用次要颜色。
定义 Provider
现在,我们的 Context Hook 使用 context 指定的默认值,当未定义 provider 时。为了能够更改值,我们需要定义一个 provider。
让我们开始定义 provider:
- 编辑
src/App.js
,并导入ThemeContext
:
import { ThemeContext } from './contexts'
- 使用 ThemeContext.Provider 组件包装整个应用程序,提供我们之前设置为默认值的相同主题:
return (
<Themecontext.Provider
value={{ primarycolor: 'deepskyblue', secondarycolor: 'coral' }}>
<div style={{ padding: 8 }}>
<Header text="React Hooks Blog" />
...
<PostList posts={posts} />
</div>
</Themecontext.Provider>
)
我们的应用程序看起来应该与以前完全相同,但现在我们使用的是 provider 的值!
动态更改主题
现在我们已经定义了一个 provider,我们可以使用它来动态更改主题。我们将使用定义当前主题的 State Hook,而不是将静态值传递给 provider。然后,我们将实现一个更改主题的组件。
在 Context Provider 使用 State Hook
首先,我们将定义一个新的 State Hook,我们将使用它来设置 context provider 的值。
让我们定义一个 State Hook,并在 context provider 中使用它:
- 编辑
src/App.js
,并导入useState
Hook:
import React, { useReducer, useEffect, usestate } from 'react'
- 在 App 组件的开头定义一个新的 State Hook;在这里,我们将默认值设置为默认主题:
export default function App () {
const [ theme, setTheme ] =
usestate({ primarycolor: 'deepskyblue', secondarycolor: 'coral' })
- 然后,我们将
theme
值传递给ThemeContext.Provider
组件:
return (
<ThemeContext.Provider value={theme}>
我们的应用程序看起来仍然和以前一样,但我们现在准备好动态更改我们的主题了!
实现 ChangeTheme 组件
主题功能的最后一部分是一个组件,可用于使用我们之前定义的 State Hook 来动态更改主题。State Hook 将重新渲染 App
组件,这将更改传递给 ThemeContext.Provider
的值,而 ThemeContext.Provider
又将重新渲染使用 ThemeContext Context Hook 的所有组件。
让我们开始实现 ChangeTheme 组件:
- 创建一个新的
src/ChangeTheme.js
文件。 - 与往常一样,我们必须先导入
React
,然后才能定义组件:
import React from 'react'
- 为了能够在以后轻松添加新主题,我们将创建一个常量
THEMES
数组,而不是手动复制和粘贴不同主题的代码。这将使我们的代码更加简洁,更易于阅读:
const THEMES = [
{ primaryColor: 'deepskyblue', secondaryColor: 'coral' },
{ primaryColor: 'orchid', secondaryColor: 'mediumseagreen' }
]
最好为硬编码的常量值指定一个特殊名称,例如将整个变量名称写成大写字母。稍后,将所有这些可配置的硬编码值放在单独的 src/config.js 文件中可能是有意义的。
- 接下来,我们定义一个组件来渲染单个
theme
:
function Themeitem ({ theme, active, onClick }) {
- 在这里,我们通过显示主要和次要颜色来渲染一个链接,并显示主题的小预览:
return (
<span onClick={onClick}
style={{ cursor: 'pointer', paddingLeft: 8, fontWeight: active ? 'bold' : 'normal' }}>
<span style={{ color: theme.primaryColor }}>Primary</span>
<span style={{ color: theme.secondaryColor }}>Secondary</span>
</span>
)
}
在这里,我们将光标设置为指针,以使元素看起来可单击。我们也可以使用一个元素;但是,如果我们没有有效的链接目标(例如单独的页面),则不建议这样做。
- 然后,我们定义
ChangeTheme
组件,它接受theme
和setTheme
props:
export default function ChangeTheme ({ theme, setTheme }) {
- 接下来,我们定义一个函数来检查主题对象是否是当前活动的主题:
function isActive (t) {
return t.primaryColor === theme.primaryColor &&
t.secondaryColor === theme secondaryColor
}
- 现在,我们使用
map
函数渲染所有可用的主题,并在单击它们时调用setTheme
函数:
return (
<div>
更改主题:
{THEMES.map((t, i) =>
<Themeitem key={'theme-' + i} theme={t}
active={isActive(t)} onClick={() => setTheme(t)}
/>
)}
</div>
)}
- 最后,我们可以在
src/App.js
中的Header
组件之后导入并渲染ChangeTheme
组件:
import ChangeTheme from './ChangeTheme'
// ...
return (
<ThemeContext.Provider value={theme}>
<div style={{ padding: 8 }}>
<Header text="React Hooks Blog" />
<changeTheme theme={theme} setTheme={setTheme} />
如我们所见,我们现在有一种方法可以在应用程序中更改主题:
更改主题后,我们的应用程序将 Context Hook 与 State Hook 结合使用
现在,我们有一个通过 Hook 使用的 context,也可以通过 Hook 进行更改!
示例代码
我们的博客应用程序中主题功能的示例代码可以在 Chapter05/chapter5_2
文件夹中找到。
只需运行 npm install
即可安装所有依赖项,运行 npm start
启动应用程序,然后在您的浏览器中访问 http://localhost:3000
(如果它没有自动打开)。
使用全局状态的 Context
在学习如何使用 React Context 在我们的博客应用程序中实现主题之后,我们现在将使用 context 来避免手动传递状态并为我们的全局应用程序 state
和 dispatch
props。
定义 StateContext
我们首先在 src/context.js
文件中定义 context。
在 src/contexts.js
中,我们定义了 StateContext
,它将存储 state
值和 dispatch
函数:
export const StateContext = React.createContext({
state: {},
dispatch: () => {}
})
我们将 state
值初始化为空对象,将 dispatch
函数初始化为空函数,当未定义 provider 时将使用该函数。
定义 Context Provider
现在,我们将在 src/App.js
文件中定义 context provider,该文件将从现有的 Reducer Hook 中获取值。
现在让我们定义全局状态的 context provider:
- 在
src/App.js
中,通过调整现有的import
语句来导入StateContext
:
import { ThemeContext, StateContext } from './contexts'
- 然后,我们通过从
App
函数返回它来定义一个新的 context provider:
return (
<StateContext.Provider value={{ state, dispatch }}>
<ThemeContext.Provider value={theme}>
...
</ThemeContext.Provider>
</StateContext.Provider>
)
现在,我们的 context provider 为应用程序的其余部分提供了 state
对象和 dispatch
函数,我们可以继续使用 Context 值。
使用 StateContext
现在我们已经定义了 context 和 provider,我们可以在各种组件中使用 state
对象和 dispatch
函数。
我们首先删除我们在 src/App.js
中手动传递给组件的 props。删除以下代码段 第 4 ~ 7 行所有的 props:
<div style={{ padding: 8 }}>
<Header text="React Hooks Blog" />
<ChangeTheme theme={theme} setTheme={setTheme} />
<UserBar user={user} dispatch={dispatch} />
{user && <CreatePost user={user} posts={posts} dispatch={dispatch} />}
<hr />
<PostList posts={posts} />
</div>
由于我们使用 context,因此不再需要手动传递 props。现在,我们可以继续重构组件。
重构用户组件
首先,我们重构用户组件,然后我们继续讨论 post 组件。
现在让我们重构与用户相关的组件:
- 编辑
src/user/UserBar.js
,并删除第7 ~ 8
行代码的 prop,因为我们不再需要手动传递它们:
export default function UserBar({ user, dispatch }) {
if (user) {
return <Logout user={user} dispatch={dispatch} />
} else {
return (
<React.Fragment>
<Login dispatch={dispatch} />
<Register dispatch={dispatch} />
</React.Fragment>
)
}
}
- 然后,我们在
src/user/UserBar.js
中导入useContext
Hook 和StateContext
,以便能够判断用户是否已登录:
import React, { useContext } from 'react'
import { StateContext } from '../contexts'
- 现在,我们可以使用 Context Hook 从我们的
state
对象获取user
状态:
export default function UserBar () {
const { state } = useContext(StateContext)
const { user } = state
- 同样,我们在
src/user/Login.js
中导入useContext
和StateContext
:
import React, { useState, useContext } from 'react'
import { StateContext } from '../contexts'
- 然后,我们删除
dispatch
prop,改用 Context Hook:
export default function Login () {
const { dispatch } = useContext(StateContext)
- 我们在
src/user/Register.js
组件中重复相同的过程:
import React, { useState, useContext } from 'react'
import { StateContext } from '../contexts'
export default function Register () {
const { dispatch } = useContext(StateContext)
- 在
src/user/Logout.js
组件中,我们执行相同的操作,但也从state
对象获取user
状态:
import React, { useContext } from 'react'
import { StateContext } from '../contexts'
export default function Logout () {
const { state, dispatch } = useContext(StateContext)
const { user } = state
我们的用户相关组件现在使用 context 而不是 props。让我们继续重构与文章相关的组件。
重构文章组件
现在,剩下要做的就是重构文章组件;那么我们的整个应用程序将使用 React Context 作为全局状态:
- 我们从
src/post/PostList.js
组件开始,我们在其中导入useContext
和StateContext
,删除 props,并使用 Context Hook:
import React, { useContext } from 'react'
import { StateContext } from '../contexts'
import Post from './Post'
export default function PostList () {
const { state } = useContext(StateContext)
const { posts } = state
- 我们对
CreatePost
组件执行相同的操作,这是我们需要重构的最后一个组件:
import React, { useState, useContext } from 'react'
import { StateContext } from '../contexts'
export default function createPost () {
const { state, dispatch } = useContext(StateContext)
const { user } = state
我们的应用程序的工作方式与以前相同,但现在我们使用全局状态的 context,这使我们的代码更加干净,并且避免了传递 props!
示例代码
我们的博客应用程序中全局状态 context 的示例代码可以在 Chapter05/chapter5_3
文件夹中找到。
只需运行 npm install
即可安装所有依赖项,运行 npm start
启动应用程序,然后在您的浏览器中访问 http://localhost:3000
(如果它没有自动打开)。
总结
在本章中,我们首先了解了 React Context 作为在多个级别的 React 组件上传递 props 的替代方案。然后,我们了解了 Context provider 和 consumer,以及通过 Hook 定义 consumer 的新方法。接下来,我们学习了何时不该使用 context,以及何时应该使用控制反转。然后,我们使用在实践中学到的知识,在博客应用程序中实现主题。最后,我们在博客应用程序中使用了全局状态的 React Context。
在下一章中,我们将学习如何使用 React 和 Hook 从服务器请求数据。然后,我们将学习 React.memo
以防止不必要的组件重新渲染,以及 React Suspense
在需要时延迟加载组件。
问题
为了回顾我们在本章中学到的内容,请尝试回答以下问题:
- Context 可以避免哪些问题?
- Context 由哪两个部分组成?
- 是否需要定义这两个部分才能使用 context?
- 使用 Hook 而不是传统的 context consumer 有什么优势?
- 什么是 context 的替代方案,我们什么时候应该使用它?
- 我们如何实现动态变化的 context?
- 什么时候对状态使用 context 有意义?
延伸阅读
如果您对我们在本章中探讨的概念的更多信息感兴趣,请查看以下阅读材料:
- 关于 React Context 的官方文档:https://reactjs.org/docs/context.html
- 有关组合与继承的更多信息:https://reactjs.org/docs/composition-vs-inheritance.html
- HTML 颜色代码列表(如果要定义新主题):https://www.rapidtables.com/web/color/html-color-codes.htm1。
评论 (0)