useContext是React提供的一个hook,它让你能够使用React的上下文特性来访问父组件提供的数据。上下文特性允许你在组件树中传递数据,而不需要通过props逐层传递。
代码结构分析
以下代码结构是用于useContext案例展示,方便理解,当熟悉之后,我们开始接下来的学习。
基本使用
1.创建 Context
使用 React.createContext 创建一个 Context 对象。可以传递一个默认值,这个默认值会在没有 Provider 包裹时使用。高亮的这句话会在介绍完Api后详细介绍。
- 基本语法:
const MyContext = React.createContext(defaultValue);
React.createContext 类似于一个store,类似于vuex,pinia创建了一个第三方中间状态管理仓库,一般都是定义在一个单独的js文件中。代码示例如下:
//useThemeContext.ts
import React from 'react'
const useThemeContext = React.createContext('default')
export default useThemeContext
2.提供 Context
使用 MyContext.Provider 来包裹需要共享数据的组件,并通过 value 属性传递数据。
- 基本语法:
<MyContext.Provider value={sharedData}>
<MyComponent />
</MyContext.Provider>
代码示例如下:
//Root.tsx
import { FC, useState } from 'react'
import useThemeContext from './useThemeContext' // 创建好的 Context 对象
// components -子组件
import CardItem from './CardItem.tsx'
const Root: FC = () => {
return (
<useThemeContext.Provider value={{ name: 'Person', age: 20 }}> //使用 MyContext.Provider 传递值
<div>我是父组件</div>
我是子组件
<CardItem></CardItem>
</useThemeContext.Provider>
)
}
export default Root
3.消费/使用Context
使用context方式有两种,一种是MyContext.Consumer,另一种就是使用useContext的hooks,下面我们都会介绍。
第一种:
使用 MyContext.Consumer来包裹需要共享数据的组件,并通过 value 属性传递数据。
<MyContext.Consumer>
{value => (
// 根据 context 值渲染的 JSX
)}
</MyContext.Consumer>
代码示例如下:
//CardItem.tsx
import { Card, Space } from 'antd'
import useThemeContext from './useThemeContext' // 创建好的 Context 对象
const CardItem = () => {
return (
<useThemeContext.Consumer> //使用MyContext.Consumer 获得context
{(ctx: any) => (
<>
<Card>
<p>{ctx.name}</p>
</Card>
</>
)}
</useThemeContext.Consumer>
)
}
export default CardItem
第二种: 使用useContext获取context
- 基本语法
const value = useContext(MyContext);
代码示例如下:
//CardItem.tsx
import { Card, Space } from 'antd'
import useThemeContext from './useThemeContext' // 假设 useThemeContext 导出了 ThemeContext
import { useContext } from 'react'
const CardItem = () => {
const ctx = useContext(useThemeContext) //使用hooks获取
return (
<>
<Card>
<p>{ctx.name}</p>
</Card>
</>
)
}
export default CardItem
还记得我们刚开始介绍所说的
"使用 React.createContext 创建一个 Context 对象。可以传递一个默认值,这个默认值会在没有 Provider 包裹时使用。"
当我们没有使用MyContext.Provider方式提供数据的时候时候,我们使用useContext获取到的值就是createContext(defaultValue)_的defaultValue。
React useContext 总结
主要的 API
-
React.createContext
:- 创建一个 Context 对象,可以传递一个默认值。
- 基本语法:
const MyContext = React.createContext(defaultValue);
-
MyContext.Provider
:- 使用
Provider
来包裹需要共享数据的组件,并通过value
属性传递数据。 - 基本语法:
<MyContext.Provider value={sharedData}> <MyComponent /> </MyContext.Provider>
- 使用
-
MyContext.Consumer
:- 使用
Consumer
来包裹需要共享数据的组件,通过函数作为子组件的方式访问Context
值。 - 基本语法:
<MyContext.Consumer> {value => ( // 根据 context 值渲染的 JSX )} </MyContext.Consumer>
- 使用
-
useContext
:- 使用
useContext
hook 来获取Context
值。 - 基本语法:
const value = useContext(MyContext);
- 使用
不常用的 API
-
Context.displayName
:displayName
是一个可以给 Context 对象设置显示名称的属性,有助于在 React DevTools 中显示更友好的调试信息。- 基本语法:
const MyContext = React.createContext(); MyContext.displayName = 'MyContextDisplayName';
-
Context.Consumer
作为 Render Props:- 虽然
Consumer
常用于函数子组件,但它也可以直接用作组件的一部分,这种用法相对不常见。 - 用法示例:
<MyContext.Consumer> {value => <MyComponent value={value} />} </MyContext.Consumer>
- 虽然