React(react18)中组件通信03——简单使用 Context 深层传递参数

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了......
  • 使用 Context 可以深层传递参数,它可以在组件树中不需要 props 将数据"直达"到所需的组件中,看官网介绍:

2. 简单例子

  • 先看实现的效果,如下是:爷爷组件给孙组件传消息:
  • 代码设计------目录结构
  • 代码设计------代码实现
    • context.js + App.js + index.js
    • Parent.jsx + Child.jsx + GrandSon.jsx

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

    javascript 复制代码
    import 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

    javascript 复制代码
    import 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

    javascript 复制代码
    import { 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;
    }
相关推荐
loey_ln25 分钟前
观察者模式和发布订阅模式
javascript·观察者模式·react.js
cnsxjean2 小时前
SpringBoot集成Minio实现上传凭证、分片上传、秒传和断点续传
java·前端·spring boot·分布式·后端·中间件·架构
ZL_5672 小时前
uniapp中使用uni-forms实现表单管理,验证表单
前端·javascript·uni-app
沉浮yu大海3 小时前
Vue.js 组件开发:构建可重用且高效的 UI 块
前端·vue.js·ui
代码欢乐豆3 小时前
软件工程第13章小测
服务器·前端·数据库·软件工程
莘薪4 小时前
JQuery -- 第九课
前端·javascript·jquery
好青崧4 小时前
CSS 样式入门:属性全知晓
前端·css·tensorflow
光头程序员4 小时前
工程化开发谷歌插件到底有爽
前端·react·工程化·前端工程化·谷歌插件
蒜蓉大猩猩4 小时前
Vue.js --- Vue3中其他组合式API
前端·javascript·vue.js·前端框架·node.js·html
铅华尽4 小时前
前端---HTML(一)
前端