在前端开发中,提到context,我们最先想到的或许是“执行上下文”。事实上,在前端开发中,context的含义有多个点:
- Execution Context(执行上下文) :在 JavaScript 中,每段代码在执行时都处于一个执行上下文中。这个上下文包含了变量对象、作用域链、this 指向等信息。JavaScript 中有全局执行上下文和函数执行上下文,它们决定了变量和函数的可访问性。
- This 指向:在 JavaScript 中,函数的执行上下文决定了
this
关键字的指向。this
指向当前执行代码的对象,它的值取决于函数被调用的方式。 - 作用域链:执行上下文中的作用域链决定了函数可以访问哪些变量和函数。
- React Context:在 React 应用中,“context” 是一种特殊的全局状态管理机制。它允许你在组件树中传递数据,而不需要手动逐层传递 props。
- …
既然是在React.js专栏中,本篇文章要讲的就是React Context
。
React Context有什么用
上文提到:
在 React 应用中,“context” 是一种特殊的全局状态管理机制。它允许你在组件树中传递数据,而不需要手动逐层传递 props。
在 React 开发中,如果不使用状态管理工具和context,数据的传递通常是通过 props 属性进行的,即将数据通过 UI 树显式传递到使用它的组件。
如上图,如果组件2-1想要使用组件1-1的数据,由于是单项数据流,数据需要状态提升到App组件,然后通过props
一层层传递。
然而,这种方式增加了组件之间的耦合性,降低组件的可复用性。在组件树比较深或者需要在多个层级之间传递相同数据时会显得非常繁琐和冗余。
为了简化跨组件传递数据的过程,React 在16.3 版本引入了 Context API。React Context
是 React 提供的原生机制,用于跨组件传递数据。
Context为整个组件树提供数据,Context 会穿过中间的任何组件。官网图示:
说到React中的状态管理,第一个想到的就是redux
。既然有了redux
,为什么要学context
?
事实上,React Redux 的实现是基于 React Context 的。React Redux 在内部利用了 React 的 Context API 来将 Redux 的 Store 提供给整个应用中的组件。
下面,我们来看context的具体使用。
context的使用
官方文档:使用 Context 深层传递参数 – React 中文文档
1. 创建context对象——React.createContext
// context.js
import React from 'react';
export const MyContext = React.createContext();
React.createContext()创建了一个上下文对象,该对象提供了Provider(提供者)
和Consumer(消费者)
。
另外,在创建context的时候可以传入参数作为默认值,这个我们到后面再说。
2. 提供数据的组件——Context.Provider
// App.jsx
import SubComponent from "./components/SubComponent";
import { MyContext } from "./context";
import { useState } from "react";
function App() {
const [count, setCount] = useState(0);
return (
// 这里的value将后面的数据放入到上下文环境中
<MyContext.Provider value={
{ count, setCount, name: '张三' }}>
{/* Provider 内部的组件树 */}
<SubComponent />
</MyContext.Provider>
);
}
export default App;
SubComponent组件中有一些子组件:
import React from 'react';
import Child1 from "./Child1";
import Child2 from "./Child2";
import Child3 from "./Child3";
export default function SubComponent() {
return (
<div>
SubComponent
<Child1 />
<Child2 />
<Child3 />
</div>
);
}
接下来我们就要在这些子组件中使用Provider提供的数据。
3. 消费数据——Context.Consumer、useContext
想要使用Context的数据,可以有两种方式。
第一种:useContext (推荐)
React 16.8 之后,引入了 Hooks, useContext
提供了一种更简洁的方式来消费 Context。该 Hook 接收一个由 React.createContext API 创建的上下文对象,并返回该 context 的当前值。
// Child1.jsx
import { useContext } from 'react';
import { MyContext } from "../context"
export default function ChildCom4() {
const { count, setCount, name } = useContext(MyContext);
return (
<div style={
{ border: '1px solid', width: "200px",}}>
Child1
<div>count:{count}</div>
<button onClick={() =