useContext介紹
接收一個(gè) context 對(duì)象(React.createContext 的返回值)并返回該 context 的當(dāng)前值。
// MyContext由createContext()創(chuàng)建
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>
)
}
調(diào)用組件
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數(shù)據(jù)流形式。使用state共享數(shù)據(jù),dispatch觸發(fā)數(shù)據(jù)修改。
const [state, dispatch] = useReducer(reducer, initialArg, init);
useReducer接收3個(gè)參數(shù):
- 接收一個(gè)函數(shù),reducer對(duì)數(shù)據(jù)的具體操作。
- state初始值。
- 接收一個(gè)函數(shù),用于state初始化。
示例
修改通過dispatch修改對(duì)象中屬性為例。
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;
構(gòu)建局部Reducer
大概介紹完useContext和useReducer用法,接下來開始進(jìn)入正題。結(jié)合useContext和useReducer構(gòu)建局部的Redux。
我們這里需要?jiǎng)?chuàng)建3個(gè)文件
- reduceAndContext.js (頂層組件,用于向下分發(fā)數(shù)據(jù))
- reducer.js (reducer的具體操作)
- childReducer.js (子組件,向reducer發(fā)送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中的數(shù)據(jù)。
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>
)
}
這里導(dǎo)出兩個(gè)模塊:
- MyContext (因?yàn)樽咏M件使用useContext需要傳入createContext,所以必須導(dǎo)出頂層組件創(chuàng)建的Context)
- Reducer (創(chuàng)建useReducer,并且把state和dispatch通過createContext提供的
Provider形式傳到子組件)
由此,子組件就可以通過useContext使用父組件傳過來的state和dispatch更新Reducer中的state數(shù)據(jù)。
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;