使用场景
父子组件自上而下的流动,需要一层层的传递,使用context就可以跨多级传递 。
context使用
首先来讲有两个概念:Provider和Consumer;在顶层组件用Provider包裹并传入value,
在子孙级的Consumer中获取value,并且能够传递函数,用来修改value的值
举例:数字增加(所有文件均在同一目录下)
Provider.tsx
import React, { createContext, ReactNode, useState, Dispatch } from 'react';
interface Injected {
counter: number,
setCounter: Dispatch<any>,
}
export const context = createContext<Injected>({} as Injected);
interface Props {
children?: ReactNode
}
export function CounterProvider({ children }: Props) {
const [counter, setCounter] = useState(0);
const value = {
counter,
setCounter,
}
return (
< context.Provider value={value}>{children}</context.Provider>
)
}
App.tsx
import React,{createContext} from 'react'
import ComponentA from './ComponentA'
import { CounterProvider } from './Provider';
const UseContext = () => {
return (
<CounterProvider>
<ComponentA />
</CounterProvider>
)
}
export default UseContext
组件A
import React from 'react'
import ComponentB from './ComponentB'
export default ()=>{
return (
<div>
<ComponentB />
</div>
)
}
组件B
import React,{useContext} from 'react'
import ComponentC from './ComponentC'
export default ()=>{
return (
<div>
<ComponentC />
</div>
)
}
组件C:使用counter
import React, { useContext } from 'react';
import { Button } from 'antd';
import { context } from './Provider';
export default () => {
return (
<context.Consumer >
{
(count)=>{
return (<div>
{count.counter}
<Button onClick={()=>{
let set = count.setCounter
set(count.counter + 1)
}}>递增</Button>
</div>)
}
}
</context.Consumer>
);
}
效果:
react-hooks 中的useContext使用
组件C:使用counter
import React, { useContext } from 'react';
import { Button } from 'antd';
import { context } from './Provider';
export default () => {
const { counter = 0, setCounter } = useContext(context) //将创建的context传入useContext,解构value值,进行数据处理
return (
<div >
<div >{counter}</div>
<Button onClick={()=>{
setCounter(counter + 1)
}}>递增</Button>
</div>
);
}
使用多个context
一层层包裹即可
<CounterProvider>
<UserProvider>
<ComponentA />
<UserProvider>
</CounterProvider>
ps注意事项
Provider, Consumer尽量不要同时使用。在同一个页面内,既创建context,又使用。
创建时,要用Provider包裹,声明要该组件下面的子孙组件可以使用context跨级获取数据。
而子孙组件,在使用时要Consumer一下,声明该组件要使用啦
import React from 'react'
import { CounterProvider } from './Provider';
import { Button } from 'antd';
import { context } from './Provider';
const UseContext = () => {
return (
<CounterProvider>
<context.Consumer>
{
(count) => {
return (<div>
{count.counter}
<Button onClick={()=>{
count.setCounter(count.counter + 1)
}}>增加</Button>
</div>)
}
}
</context.Consumer>
</CounterProvider>
)
}
export default UseContext
错误用法
import React,{createContext,useContext} from 'react'
import { CounterProvider } from './Provider';
import { Button } from 'antd';
import { context } from './Provider';
const UseContext = () => {
const { counter = 0, setCounter } = useContext(context)
return (
<CounterProvider>
{counter} //useContext使用时不需要Consumer包裹
<Button onClick={()=>{
setCounter(counter + 1)
}}>增加</Button>
</CounterProvider>
)
}
export default UseContext