ReactJS - 使用 useContext
Context 是 React 中的重要概念之一。它提供了将信息从父组件传递到其所有子组件到任何嵌套级别的能力,而无需通过每个级别的 props 传递信息。Context 将使代码更具可读性和易于理解。Context 可用于存储不变或变化极小的信息。context 的一些用例如下 −
应用程序配置
当前经过身份验证的用户信息
当前用户设置
语言设置
按应用程序/用户进行主题/设计配置
React 提供了一个特殊的Hooks(钩子) useContext 来访问和更新函数组件中的上下文信息。让我们在本章中学习上下文及其相应的Hooks(钩子)。
上下文如何工作?
在理解 useContext Hooks(钩子)之前,让我们重新回顾一下上下文的基本概念及其工作原理。上下文有四个部分,
创建新上下文
在根组件中设置上下文提供程序
在需要上下文信息的组件中设置上下文消费者
访问上下文信息并在渲染方法中使用它
让我们创建一个应用程序来更好地理解上下文及其用法。让我们创建一个全局上下文,用于在应用程序根组件中维护主题信息,并在子组件中使用它。
首先,使用以下命令创建并启动应用程序,
create-react-app myapp cd myapp npm start
接下来,在 components 文件夹 (src/components/HelloWorld.js) 下创建一个组件 HelloWorld
import React from "react";
import ThemeContext from "../ThemeContext";
class HelloWorld extends React.Component {
render() {
return <div>Hello World</div>
}
}
export default HelloWorld
接下来,创建一个新的上下文(src/ThemeContext.js)用于维护主题信息。
import React from 'react'
const ThemeContext = React.createContext({
color: 'black',
backgroundColor: 'white'
})
export default ThemeContext
这里,
使用 React.createContext 创建一个新上下文。
上下文被建模为具有样式信息的对象。
设置文本颜色和背景的初始值。
接下来,通过包含 HelloWorld 组件和主题提供程序以及主题上下文的初始值来更新根组件 App.js。
import './App.css';
import HelloWorld from './components/HelloWorld';
import ThemeContext from './ThemeContext'
function App() {
return (
<ThemeContext.Provider value={{
color: 'white',
backgroundColor: 'green'
}}>
<HelloWorld />
</ThemeContext.Provider>
);
}
export default App;
这里使用了 ThemeContext.Provider,这是一个非可视组件,用于设置其所有子组件中使用的主题上下文的值。
接下来,在 HelloWorld 组件中包含一个上下文消费者,并使用 HelloWorld 组件中的主题信息来设置 hello world 消息的样式。
import React from "react";
import ThemeContext from "../ThemeContext";
class HelloWorld extends React.Component {
render() {
return (
<ThemeContext.Consumer>
{
( {color, backgroundColor} ) =>
(<div style={{
color: color,
backgroundColor: backgroundColor }}>
Hello World
</div>)
}
</ThemeContext.Consumer>)
}
}
export default HelloWorld
这里我们有,
使用ThemeContext.Consumer,这是一个非可视化组件,提供对当前主题上下文详细信息的访问
使用函数表达式获取ThemeContext.Consumer中的当前上下文信息
使用对象解构语法获取主题信息并设置color和backgroundColor变量中的值。
使用主题信息通过style属性设置组件样式。
最后,打开浏览器并检查应用程序的输出
useContext 的签名
useContext 的签名如下 −
let contextValue = useContext( <contextName> )
这里,
contextName 指的是要访问的上下文的名称。
contextValue 指的是所引用上下文的当前值。
使用Hooks(钩子)访问上下文的示例代码如下 −
const theme = useContext(ThemContext)
通过hook
让我们更新我们的应用程序并使用上下文Hooks(钩子)代替上下文消费者。
首先,将 HelloWorld 组件转换为函数组件。
import React from "react";
function HelloWorld() {
return <div>Hello World</div>
}
export default HelloWorld
接下来,通过 useContext hook 访问上下文的当前值
import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
let theme = useContext(ThemeContext)
return <div>Hello World</div>
}
export default HelloWorld
接下来,更新渲染函数以使用通过上下文获取的主题信息。
import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
let theme = useContext(ThemeContext)
return (
<div style={{
color: theme.color,
backgroundColor: theme.backgroundColor }}>
Hello World
</div>
)
}
export default HelloWorld
这里我们有,
使用 useContext 访问 ThemeContext 上下文信息。
使用 ThemeContext 信息设置背景颜色和文本颜色。
最后,打开浏览器并检查应用程序的输出。
更新上下文
在某些情况下,更新上下文信息是必要的。例如,我们可以提供一个选项来让用户更改主题信息。当用户更改主题时,上下文应该得到更新。更新上下文将重新渲染所有子组件,这将改变应用程序的主题。
React 提供了一个使用 useState 和 useContext Hooks(钩子)更新上下文的选项。让我们更新我们的应用程序以支持主题选择。
首先,更新根组件 App.js 并使用 useState Hooks(钩子)来管理主题信息,如下所示 −
import './App.css'
import { useState } from 'react'
import HelloWorld from './components/HelloWorld'
import ThemeContext from './ThemeContext'
function App() {
let initialTheme = {
color: 'white',
backgroundColor: 'green'
}
const [theme, setTheme] = useState(initialTheme)
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<HelloWorld />
</ThemeContext.Provider>
);
}
export default App;
这里我们有,
使用 useState Hooks(钩子)在根组件的状态中设置主题信息。
主题更新函数,useState 返回的 useTheme 也作为主题信息的一部分包含在上下文中。
接下来,更新 HelloWorld 组件以获取存储在上下文中的主题信息。
import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
let { theme, setTheme } = useContext(ThemeContext)
return (<div style={{
color: theme.color,
backgroundColor: theme.backgroundColor }}>
<div>Hello World</div>
</div>)
}
export default HelloWorld
接下来,通过下拉选项为用户提供更改主题的选项。
import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
let { theme, setTheme } = useContext(ThemeContext)
return (<div style={{
color: theme.color,
backgroundColor: theme.backgroundColor }}>
<div>
<select value={theme.backgroundColor}>
<option value="green">Green</option>
<option value="red">Red</option>
</select>
<div>Hello World</div>
</div>)
}
export default HelloWorld
这里我们有,
添加了一个下拉框,其中有两个选项,绿色和红色。
使用当前主题值 value={theme.backgroundColor) 设置下拉框的当前值。
接下来,每当用户通过 onChange 事件更改主题时,更新上下文。
import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
let { theme, setTheme } = useContext(ThemeContext)
return (<div style={{
color: theme.color,
backgroundColor: theme.backgroundColor }}>
<div>
<select value={theme.backgroundColor}
onChange = {
(e) => {
setTheme({
...theme,
backgroundColor: e.target.value
})
}} >
<option value="green">Green</option>
<option value="red">Red</option>
</select>
</div>
<div>Hello World</div>
</div>)
}
export default HelloWorld
这里我们有,
将 onChange 事件附加到下拉框。
在事件处理程序中使用 setTheme 函数,并将主题的背景颜色更新为用户选择的颜色。
根组件和 HelloWorld 组件的完整代码如下 &miinus;
import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
let { theme, setTheme } = useContext(ThemeContext)
return (<div style={{
color: theme.color,
backgroundColor: theme.backgroundColor }}>
<div>
<select value={theme.backgroundColor}
onChange= {
(e) => {
setTheme({
...theme,
backgroundColor: e.target.value
})
}
} >
<option value="green">Green</option>
<option value="red">Red</option>
</select>
</div>
<div>Hello World</div>
</div>)
}
export default HelloWorld
接下来,打开浏览器并检查应用程序。
当用户选择不同的背景颜色时,它将更新上下文,因此,它将以新主题重新渲染组件,如下所示 −
摘要
上下文降低了在 React 应用程序中维护全局数据的复杂性。上下文Hooks(钩子)通过简化访问和更新(通过 useState)上下文进一步降低了复杂性。

