不说废话,直接上代码
随便写了一个reducer.ts
export interface StateProps {
id: number;
text: string;
isFinished: boolean;
}
export interface ActionProps {
type: string;
[key: string]: any;
}
const reducer = (state: StateProps[], action: ActionProps) => {
switch (action.type) {
case "ADD":
return [...state, action.todo];
case "CHANGEFINISHED":
return state.map((item) => {
if (item.id === action.id) {
return Object.assign({}, item, {
isFinished: !item.isFinished,
});
}
return item;
});
default:
return state;
}
};
export default reducer;
然后看封装的createContext.tsx文件
import React, { createContext, Dispatch } from "react";
import { StateProps, ActionProps } from "../store/reducer";
import _ from "lodash";
export interface ContextProps {
value: {
state: StateProps[];
dispatch: Dispatch<ActionProps>;
};
}
export const MyContext = createContext({} as ContextProps);
const MyProvide = (props: React.PropsWithChildren<ContextProps>) => {
return (
<MyContext.Provider value={_.omit(props, "children")}>
{props.children}
</MyContext.Provider>
);
};
export default MyProvide;
如何使用这个createContext.tsx呢
import React, {
useRef,
FC,
useReducer,
Dispatch,
} from "react";
import ToDoInput from "./todo-input";
import MyProvide from "./createContext";
import reducer, { StateProps, ActionProps } from "../store/reducer";
interface ContextProps {
state: StateProps[];
dispatch: Dispatch<ActionProps>;
}
const ToDo: FC = () => {
const initState: StateProps[] = [];
const [state, dispatch] = useReducer(reducer, initState);
const transferParameter: ContextProps = { state, dispatch };
return (
<>
<MyProvide value={transferParameter}>
<ToDoInput /> // 子组件
</MyProvide>
</>
);
};
export default ToDo;
然后你在子组件可以获取到state和dispatch,并且通过dispatch发送事件
import React, { useContext, useEffect, useRef } from "react";
import { MyContext } from "./my-provide";
const ToDoInput = () => {
const { value: { dispatch, state } } = useContext(MyContext);
const inputRef = useRef<HTMLInputElement>(null);
const addTodoHandle = () => {
const value = inputRef.current!.value;
dispatch({
type: "ADD",
todo: {
id: new Date().getTime(),
text: value,
isFinished: false,
},
});
inputRef.current!.value = '';
};
useEffect(() => {
inputRef.current!.focus();
}, [])
return (
<>
<input
type="text"
placeholder="请输入"
ref={inputRef}
/>
<button onClick={addTodoHandle}>添加</button>
</>
);
};
export default ToDoInput;
子组件发送dispatch事件改变state之后,在父组件里面就能接收到,多层通信也是这样操作