React第十节组件之间传值之context

1、Context 使用creatContext() 和 useContext() Hook 实现多层级传值

概述:

在我们想要每个层级都需要某一属性,或者祖孙之间需要传值时,我们可以使用 props 一层一层的向下传递,或者我们使用更便捷的方案,用 creatContext() 和 useContext() 进行隔代之间传值,这种情况下,我们只需要在使用的组件中书写,而不用每一层级都进行书写

使用中注意事项

a、必须使用 Provider 组件,必须使用 value 接收要传递的 属性:

b、下级会向上找最近 的 Provider 获取其传入的 value

c、传入的 value 可以是任意类型的属性

javascript 复制代码
extport default function MyPar(){
  return(
      <>
          <MyCom.Provider value={属性}>
          </MyCom.Provider>
      </>
  )
}

1.1、基本用法实现上下级数据共享

首先创建通用 ComContext文件

javascript 复制代码
import { createContext } from "react";
// 创建一个 UserInfoContext 组件
export const UserInfoContext = createContext()

其次创建最终使用组件 UserInfo

javascript 复制代码
import {useContext} from 'react'
import { UserInfoContext } from './ComContext'
export default function UseInfo() {
    // 通过 useContext Hook 接收上级 UserInfoContext 传入的内容,总是获取距离最近的 Provider 的 value 值
    const userInfo = useContext(UserInfoContext)
    console.log('==userInfo===', userInfo)
  return (
    <div>
      <h3>用户信息</h3>
      <p>名称:{userInfo.name}</p>
      <p>年龄:{userInfo.age}</p>
    </div>
  )
}

最后在父组件中调用上面两个组件

javascript 复制代码
import { UserInfoContext } from './ComContext'
import UseInfo from './UseInfo'
export default function MyContext2() {

    const userInfo = {
        name: 'Andy',
        age: 18
    }
  return (
    <>
        <h2>第一级:</h2>
        {/* 将普通对象传给下级 */}
        <UserInfoContext.Provider value={userInfo}>
            {/* 这里 不管写多少个 UseInfo 组件,都可以接收到 传入的 userInfo 对象 */}
            <UseInfo></UseInfo>
            <UseInfo></UseInfo>
            <UseInfo></UseInfo>
        </UserInfoContext.Provider>
    </>
  )
}

1.2、Context 与 useState() 使用

通过 useState() 动态修改 userInfo 数据,

javascript 复制代码
import { useState} from 'react'
import { UserInfoContext } from './ComContext'
import UseInfo from './UseInfo'
export default function MyContext2() {
    const [userInfo, setUseInfo] = useState({
        name: 'Andy',
        age: 18
    })
    const hanldeChangeUserInfo = () => {
        setUseInfo({...userInfo, name: `${userInfo.name} + 1`})
    }
  return (
    <>
        <h2>第一级:</h2>
        <button onClick={hanldeChangeUserInfo}>修改name</button>
        <UserInfoContext.Provider value={userInfo}>
            {/* 在下级接收的 userInfo 会实时更新 */}
            <UseInfo></UseInfo>
        </UserInfoContext.Provider>
    </>
  )
}

1.3、Context 树形结构示例

文件目录

声明levelContext文件

复制代码
import { createContext } from "react";
export const LevelContext = createContext(0)

声明 HeadTitle文件

复制代码
import  { useContext } from 'react'
import { LevelContext } from "./LevelContext";
export default function HeadTitle({children}) {
	//  使用 LevelContext
    const level = useContext(LevelContext)
    {
        switch(level) {
            case 1:
            return <h1>{`第${level}级`}</h1>
            case 2:
            return <h2>{`第${level}级`}</h2>
            case 3:
            return <h3>{`第${level}级`}</h3>
            case 4:
            return <h4>{`第${level}级`}</h4>
            case 5:
            return <h5>{`第${level}级`}</h5>
        }
    }
}

声明 ContMain 文件

这里使用 nanoid 插件,生成随机id,需要自行安装 yarn add nanoid

复制代码
import React, { useContext } from 'react'
import HeadTitle from './HeadTitle'
import { LevelContext } from './LevelContext'
import { nanoid } from 'nanoid';
import './index.scss'
export default function ContMain({children}) {
    const level = useContext(LevelContext)
    return (
            <div className="container">
                { 
                    children && children.length && children?.map((item, index) => 
                            <>
                            // 这样 HeadTitle 组件中才能获取到 value 值
                                <LevelContext.Provider key={`${nanoid()}4444`} value={item.level} >
                                    <HeadTitle ></HeadTitle>
                                    <p>姓名:{item.name}</p>
                                    <p>年龄:{item.age}</p>
                                    {
                                        item && item?.children && item?.children.length && (
                                            <div style={{marginLeft: `${item.level * 20}px`}}>
                                            // 自调用当前组件
                                                <ContMain>{[...item.children]}</ContMain>
                                            </div>
                                        ) 
                                    }
                                </LevelContext.Provider>
                            </>
                    )
                }
            </div>
    )
}

声明index 文件

复制代码
import ContMain from './ContMain'
import { userInfoArr } from './mock.js'
import { LevelContext } from './LevelContext'
export default function MyContext3() {
  return (
    <>
        <h1>父级</h1>
        <LevelContext.Provider value={1}>
            <ContMain >{[...userInfoArr]}</ContMain>
        </LevelContext.Provider>
        
    </>
  )
}

效果如图:

相关推荐
转转技术团队9 分钟前
多代理混战?用 PAC(Proxy Auto-Config) 优雅切换代理场景
前端·后端·面试
南囝coding10 分钟前
这几个 Vibe Coding 经验,真的建议学!
前端·后端
gnip24 分钟前
SSE技术介绍
前端·javascript
yinke小琪39 分钟前
JavaScript DOM节点操作(增删改)常用方法
前端·javascript
枣把儿43 分钟前
Vercel 收购 NuxtLabs!Nuxt UI Pro 即将免费!
前端·vue.js·nuxt.js
望获linux44 分钟前
【Linux基础知识系列】第四十三篇 - 基础正则表达式与 grep/sed
linux·运维·服务器·开发语言·前端·操作系统·嵌入式软件
爱编程的喵1 小时前
从XMLHttpRequest到Fetch:前端异步请求的演进之路
前端·javascript
喜欢吃豆1 小时前
深入企业内部的MCP知识(三):FastMCP工具转换(Tool Transformation)全解析:从适配到增强的工具进化指南
java·前端·人工智能·大模型·github·mcp
豆苗学前端1 小时前
手把手实现支持百万级数据量、高可用和可扩展性的穿梭框组件
前端·javascript·面试
不见_1 小时前
不想再写周报了?来看看这个吧!
前端·命令行