useContext介绍
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。
// MyContext由createContext()创建
let count = useContext(MyContext);
常用于容器组件向子组件传值
示例
这里以父组件向子组件传count累加值为例
定义容器组件
import { createContext } from "react";
export let MyContext = createContext();
定义子组件
import React, { useContext } from "react";
import { MyContext } from "./myContext";
export default () => {
let count = useContext(MyContext);
return (
<h3>子组件{count}</h3>
)
}
调用组件
import React, { createContext, useContext, useState } from "react";
import { MyContext } from "./myContext";
import { Button } from "antd";
function UseContext() {
const [count, setCount] = useState(0);
return (
<>
<MyContext.Provider value={count}>
<ChildContext/>
</MyContext.Provider>
<Button type={"primary"} onClick={() => {
setCount(count + 1);
}}>
change count
</Button>
</>
)
}
export default UseContext;
useReducer介绍
类似于Redux数据流形式。使用state共享数据,dispatch触发数据修改。
const [state, dispatch] = useReducer(reducer, initialArg, init);
useReducer接收3个参数:
- 接收一个函数,reducer对数据的具体操作。
- state初始值。
- 接收一个函数,用于state初始化。
示例
修改通过dispatch修改对象中属性为例。
import React, { useReducer } from "react";
import { Button } from "antd";
function UseReducer() {
const [state, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'setName':
return {
...state,
name: action.name
}
default:
return state;
}
}, { name: 'init' });
return (
<>
<h1>{state.name}</h1>
<Button type={"primary"} onClick={() => {
dispatch({
type: 'setName',
name: 'hzm'
})
}}>setName</Button>
</>
)
}
export default UseReducer;
构建局部Reducer
大概介绍完useContext和useReducer用法,接下来开始进入正题。结合useContext和useReducer构建局部的Redux。
我们这里需要创建3个文件
- reduceAndContext.js (顶层组件,用于向下分发数据)
- reducer.js (reducer的具体操作)
- childReducer.js (子组件,向reducer发送dispatch)
reduceAndContext.js
import React from "react";
import { Reducer } from "./reducer";
import ChildReducer from "./childReducer";
function ReducerAndContext() {
return (
<Reducer>
<ChildReducer/>
</Reducer>
)
}
export default ReducerAndContext;
reduceAndContext.js 中引入reducer.js和childReducer.js,让<Reducer>包裹下的<ChildReducer/>组件能接收到Reducer中的数据。
reducer.js
import React, { createContext, useReducer } from "react";
export const MyContext = createContext();
const reducer = (state, action) => {
switch (action.type) {
case 'setName':
return {
...state,
name: action.name
}
default:
return state;
}
}
const defaultData = {
name: 'init',
}
export function Reducer(props) {
const [state, dispatch] = useReducer(reducer, defaultData);
return (
<MyContext.Provider value={{ state, dispatch }}>
{props.children}
</MyContext.Provider>
)
}
这里导出两个模块:
- MyContext (因为子组件使用useContext需要传入createContext,所以必须导出顶层组件创建的Context)
- Reducer (创建useReducer,并且把state和dispatch通过createContext提供的
Provider
形式传到子组件)
由此,子组件就可以通过useContext使用父组件传过来的state和dispatch更新Reducer中的state数据。
childReducer.js
import React, { useContext } from "react";
import { MyContext } from "./reducer";
import { Button } from "antd";
function ChildReducer() {
const { state, dispatch } = useContext(MyContext);
return (
<>
<h1>{state.name}</h1>
<Button type={"primary"} onClick={() => {
dispatch({
type: 'setName',
name: 'hzm'
})
}}>
change reducer
</Button>
</>
)
}
export default ChildReducer;
网友评论