You Might Not Need Redux. —— Dan Abramov然而咱们能够用 useReducer 和 useContext ~
后面说的话:useContext 能够实现状态共享,useReducer 能够实现犹如 redux 状态管理器 dispatch 的性能 。这样一来,咱们就能够拿这两个hook来实现一个简略的状态管理器了。如果再退出ts呢,咱们能够想到的是本人定义的诸多 type,通过ts加编辑器的反对,在咱们眼前出现的那种愉悦感 ~
在我的项目中,咱们可能会有多个状态须要共享,咱们可能会在登录后异步申请获取用户信息,而后在其余页面会用到这个用户信息... 。
那就让咱们就用这两个hook举个例子吧:( 这两个hook还不理解的小伙伴,能够看上一篇文章介绍,点我点我 )
实现异步获取用户信息的相干文件userInfo/index.declare.ts
export interface IState { id?: string; name?: string; isFetching?: boolean; failure?: boolean; message?: string;}type TType = | "ASYNC_SET_USER_INFO" | "FETCHING_START" | "FETCHING_DONE" | "FETCHING_FAILURE";export interface IAction { type: TType; payload?: IState;}这个文件这里把它提取进去,申明了根本的 state 、type的束缚与action,参数用 payload 来接管
userInfo/index.tsx
import React, { useReducer, createContext, useContext } from "react";import { IState, IAction } from "./index.declare";// 初始化状态const initialState: IState = { id: "", name: "", isFetching: false, failure: false, message: ""};// 创立一个 context,并初始化值const context: React.Context<{ state: IState; dispatch?: React.Dispatch<IAction>;}> = createContext({ state: initialState});// reducerconst reducer: React.Reducer<IState, IAction> = ( state, { type, payload }): IState => { switch (type) { case "ASYNC_SET_USER_INFO": { const { id, name, message } = payload!; return { ...state, id, name, message }; } case "FETCHING_START": { return { ...state, failure: false, isFetching: true }; } case "FETCHING_DONE": { return { ...state, isFetching: false }; } case "FETCHING_FAILURE": { return { id: "", name: "", failure: true, message: payload?.message }; } default: throw new Error(); }};/** * mock:模仿了申请接口的异步期待 */const request = (id: string): Promise<any> => { return new Promise((resolve, reject) => { setTimeout(() => { if (id === "998") { resolve({ id: "998", name: "liming", message: "获取用户胜利" }); } else { reject(`找不到id为${id}的用户`); } }, 1000); });};/** * dispatch 异步/同步 高阶函数 */const dispatchHO = (dispatch: React.Dispatch<IAction>) => { return async ({ type, payload }: IAction) => { if (type.indexOf("ASYNC") !== -1) { dispatch({ type: "FETCHING_START" }); try { const { id, name, message } = await request(payload!.id!); dispatch({ type, payload: { id, name, message } }); } catch (err) { dispatch({ type: "FETCHING_FAILURE", payload: { message: err } }); } dispatch({ type: "FETCHING_DONE" }); } else { dispatch({ type, payload }); } };};/** * ProviderHOC 高阶组件 */export const ProviderHOC = (WrappedComponent: React.FC) => { const Comp: React.FC = (props) => { const [state, dispatch] = useReducer(reducer, initialState); return ( <context.Provider value={{ state, dispatch: dispatchHO(dispatch) }}> <WrappedComponent {...props} /> </context.Provider> ); }; return Comp;};/** * 封装 useContext */export const useContextAlias = () => { const { state, dispatch } = useContext(context); return [state, dispatch] as [IState, React.Dispatch<IAction>];};解释:
...