React(react18)中组件通信03------简单使用 Context 深层传递参数
- [1. 前言](#1. 前言)
-
- [1.1 React中组件通信的其他方式](#1.1 React中组件通信的其他方式)
- [1.2 引出 Context](#1.2 引出 Context)
- [2. 简单例子](#2. 简单例子)
- [3. 语法说明](#3. 语法说明)
-
- [3.1 createContext(defaultValue)](#3.1 createContext(defaultValue))
- [3.2 value](#3.2 value)
- [3.3 useContext(SomeContext)](#3.3 useContext(SomeContext))
- [4. 总结](#4. 总结)
-
- [4.1 Context](#4.1 Context)
-
- [4.1.1 Context 小总结](#4.1.1 Context 小总结)
- [4.1.2 Context 应用场景](#4.1.2 Context 应用场景)
- [4.1.3 Context-官网](#4.1.3 Context-官网)
- [4.2 createContext](#4.2 createContext)
- [4.3 useContext()](#4.3 useContext())
- [5. 附代码](#5. 附代码)
1. 前言
1.1 React中组件通信的其他方式
1.2 引出 Context
- 需求场景:
- 我们知道,如果父传子,可以通过props,如果子再传孙,还可以通过props,但是如果家族庞大,组件关系如果一颗大树,一直向下传递,这时候如果还用props,明显就显得有点费劲了。
- 而且如果这个参数子不要孙要的情况,通过props逐层传递也不是很合理。
- 再或者,如果这个后代离根太远了,如果还用props逐层传递下去,那么传递 props 会变的十分冗长和不便。
- 这就需要考虑怎么能跳过中间代还能给后后代传递呢?这就需要接下来要介绍的Context了......
- 我们知道,如果父传子,可以通过props,如果子再传孙,还可以通过props,但是如果家族庞大,组件关系如果一颗大树,一直向下传递,这时候如果还用props,明显就显得有点费劲了。
- 使用 Context 可以深层传递参数,它可以在组件树中不需要 props 将数据"直达"到所需的组件中,看官网介绍:
2. 简单例子
- 先看实现的效果,如下是:爷爷组件给孙组件传消息:
- 代码设计------目录结构
- 代码设计------代码实现
- context.js + App.js + index.js
- Parent.jsx + Child.jsx + GrandSon.jsx
- context.js + App.js + index.js
3. 语法说明
3.1 createContext(defaultValue)
- 如下:
3.2 value
value
:该值为你想传递给所有处于这个 provider 内读取该 context 的组件,无论它们处于多深的层级。context 的值可以为任何类型。该 provider 内的组件可通过调用 useContext(SomeContext) 来获取它上面最近的 context provider 的 value。
3.3 useContext(SomeContext)
- 在组件的顶层调用 useContext 来读取和订阅 context。
4. 总结
4.1 Context
4.1.1 Context 小总结
- Context 使组件向其下方的整个树提供信息。
- 传递 Context 的方法:
- 通过
export const MyContext = createContext(defaultValue)
创建并导出 context。 - 在无论层级多深的任何子组件中,把 context 传递给
useContext(MyContext)
Hook 来读取它。 - 在父组件中把 children 包在
<MyContext.Provider value={...}
> 中来提供 context。
- 通过
- Context 会穿过中间的任何组件。
- Context 可以让你写出 "较为通用" 的组件。
- 在使用 context 之前,先试试传递 props 或者将 JSX 作为 children 传递。
4.1.2 Context 应用场景
- 看官网介绍:
4.1.3 Context-官网
4.2 createContext
- 上下文使得组件能够无需通过显式传递参数的方式 将信息逐层传递。
- 在任何组件外调用 createContext 来创建一个或多个上下文。
因为,通常,来自不同文件的组件都会需要读取同一个 context。因此,在一个单独的文件内定义 context 便成了常见做法。你可以使用 export 语句 将其导出,以便其他文件读取使用 - 参考官网:
https://zh-hans.react.dev/reference/react/createContext#createcontext.
4.3 useContext()
- 如果 React 没有在父树中找到该特定 context 的任何 provider,useContext() 返回的 context 值将等于你在 创建 context 时指定的 默认值;
- 注意,只有在 上层根本没有匹配的 provider 时才使用
createContext(defaultValue)
调用的默认值。如果存在<SomeContext.Provider value={undefined}>
组件在父树的某个位置,调用 useContext(SomeContext)
的组件 将会 接收到undefined
作为 context 的值。 - 参考官网:
https://zh-hans.react.dev/reference/react/useContext.
5. 附代码
-
context.js
javascript/** * 1. 通常,来自不同文件的组件都会需要读取同一个 context。 * 2. 因此,在一个单独的文件内定义 context 便成了常见做法。 * 3. 你可以使用 export 语句 将其导出,以便其他文件读取使用 */ import { createContext } from "react"; const MessegeContext = createContext(); export default MessegeContext; // import { createContext } from 'react'; // export const ThemeContext = createContext('light'); // export const AuthContext = createContext(null);
-
Parent.jsx
javascriptimport React from "react"; import Child from "./Child"; import './index.css' import { useState } from "react"; import MessegeContext from "./context.js"; function Parent() { const [notice, setNotice] = useState('孙子,你真棒!!'); return( // <div className="parent"> // 我是父组件! // <div className="child"> // <Child notice={'通知------今天放假!'}/> // </div> // </div> // 这里的属性,只能用 value <MessegeContext.Provider value={notice}> <div className="parent"> 我是父组件! <div className="child"> <Child notice={'通知------今天放假!'}/> </div> </div> </MessegeContext.Provider> ) } export default Parent;
-
Child.jsx
javascriptimport React from "react"; import GrandSon from "./GrandSon"; import './index.css' function Child(props){ return( <div> 我是子组件!!! <br /><br /> 收到来自于父组件的数据:{props.notice} <br /><br /> <div className="grandSon"> <GrandSon /> </div> </div> ) } export default Child;
-
GrandSon.jsx
javascriptimport { useContext } from "react" import MessegeContext from "./context.js"; export default function GrandSon(){ // 在组件的顶层调用 useContext 来读取和订阅 context。 const msgContent = useContext(MessegeContext); console.log(msgContent); return( <div> 我是孙组件!! <br /> 我收到爷爷的信息是:{msgContent} </div> ) }
-
componenet-->index.css
html.parent{ background-color: blueviolet; border: 1px solid; height: 900px; width: 600px; text-align: center; } .child{ background-color: green; height: 300px; margin: 20px; } .grandSon{ background-color: grey; height: 150px; margin: 20px; }