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>
        
    </>
  )
}

效果如图:

相关推荐
觉醒法师4 分钟前
HarmonyOS开发 - 电商App实例二( 网络请求http)
前端·http·华为·typescript·harmonyos·ark-ts
沈剑心4 分钟前
Kotlin的协程,真能提升编程效率么?
android·前端·kotlin
堕落年代15 分钟前
Vue主流的状态保存框架对比
前端·javascript·vue.js
没资格抱怨16 分钟前
el-pagination的使用说明
javascript·vue.js·elementui
OpenTiny社区25 分钟前
TinyVue的DatePicker 组件支持日期面板单独使用啦!
前端·vue.js
冴羽26 分钟前
Svelte 最新中文文档教程(22)—— Svelte 5 迁移指南
前端·javascript·svelte
树上有只程序猿30 分钟前
Vue3组件通信:多个实战场景,轻松玩转复杂数据流!
前端·vue.js
青红光硫化黑35 分钟前
React基础之useEffect
javascript·react.js·ecmascript
剪刀石头布啊38 分钟前
css属性值计算过程
前端·css
bin915342 分钟前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14基础固定表头示例
前端·javascript·vue.js·ecmascript·deepseek