useReducer的缺陷
useReducer和useState一样,需要通过props在子组件中传递,很麻烦,所以可以把useReducer返回的状态和dispatch通过useContext在子组件中传递
使用方法
创建reducer
const [info, dispatch] = useReducer(mapReducer,initMap);
创建状态和dispatch的上下文
MapStateReducerContext.tsx
import React from "react";
export const MapStateContext=React.createContext<any>(null);
export const MapDispatchContext=React.createContext<any>(null);
设置状态和dispatch到上下文中
import {MapStateContext,MapDispatchContext} from './MapStateReducerContext';
return (
<MapStateContext.Provider value={info}>
<MapDispatchContext.Provider value={dispatch}>
{children}
</MapDispatchContext.Provider>
</MapStateContext.Provider>
);
使用reducer
import * as action from './MapReducerAction'; //导入action
const state=useContext(MapStateContext); //获取状态上下文
const dispatch=useContext(MapDispatchContext);//获取dispatch上下文
dispatch(action.<action函数>(action参数)
案例
import React, { useReducer,useState,useContext } from 'react';
import * as action from './MapReducerAction';
import {mapReducer} from './MapReducer';
import {MapStateContext,MapDispatchContext} from './MapStateReducerContext';
const initMap = {
name: 'px',
info: {
age: '18',
address: 'beijing'
}
}
function MapItem({ key1, value }: { key1: string; value: string}) {
const [readOnly, setReadOnly] = useState(true);
const [item, setItem] = useState(value);
const dispatch=useContext(MapDispatchContext);
function editItem() {
if (readOnly) {
setReadOnly(false);
} else {
switch(key1){
case 'name':
dispatch(action.update_name(item));
break;
case 'info.age':
dispatch(action.update_age(item));
break;
case 'info.address':
dispatch(action.update_address(item));
break;
default:
console.log('error key1',key1);
break;
}
setReadOnly(true);
}
}
if (readOnly) {
return (<div>{value}<button onClick={() => editItem()}>编辑</button></div>);
} else {
return (
<div>
<input
type="text"
value={item}
onChange={(e) => setItem(e.target.value)}
/>
<button onClick={() => editItem()}>保存</button>
</div>
);
}
}
export function MapStateReducerContextTest() {
const [info, dispatch] = useReducer(mapReducer,initMap);
return (
<MapStateContext.Provider value={info}>
<MapDispatchContext.Provider value={dispatch}>
<MapItem key1='name' value={info.name} ></MapItem>
<MapItem key1='info.age' value={info.info.age} ></MapItem>
<MapItem key1='info.address' value={info.info.address} ></MapItem>
</MapDispatchContext.Provider>
</MapStateContext.Provider>
);
}