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>
</>
)
}
效果如图: