useContext + useReducer 实现redux

403 阅读1分钟

图片1.jpg

大家都知道redux是一个封装好的react集中式数据流管理方案

我们今天来自己通过react hooks的两个钩子函数useContext()、useReducer() 来实现一下redux功能

首先,创建一个全局对象context对象

image.png

创建一个存放常量的文件,方便action function和reducer函数根据常量完成不同业务,直接引用,无需多次创建

image.png

action function文件

image.png

reducer 函数

image.png

App组件

import React,{useReducer} from "react";
import {GetEmail} from "./GetEmail";
import {user} from './reducers/user';
import Child from './Child';

//初始state值
const initialState = {
    user:null
}
//判断是否是promise对象
function isPromise(obj){
    return(
        !!obj && (typeof obj==="object"||typeof obj==="function")
        &&typeof obj.then ==="function"
    );
}
function wrapperDispatch(dispatch){
    return function(action){//处理后代传过来的action
        if(isPromise(action.payload)){//判断是否是Promise对象
            action.payload.then(res=>{//axios请求成功
                //发送带数据的action给注册的reducer函数
                dispatch({type:action.type,payload:res})
            })
        }else{//普通action对象直接转发action给注册的reducer函数
            dispatch(action);
        }
    }
}
const App = () => {
    //让静态组件拥有state,通过dispatch传递action给reducer函数来改变state
    let [state,dispatch] = useReducer(user,initialState);
    //                              注册的reducer函数 ,初始state
    return (
        <>
            <h3>App组件</h3>
            <GetEmail.Provider value={{state,dispatch:wrapperDispatch(dispatch)}} >
                //将全局context里面的内容向后代传递
                <Child />
            </GetEmail.Provider>
        </>
     );
}
export default App;

Child组件

image.png

GrandChild组件

image.png

执行流程概括:

首先按照顺序渲染出来

image.png

当点击get email按钮时,发送action(调用的是actions function的fetch_user()) 将这个action给App组件的wrapperDispatch,判断是否是异步请求,等异步请求成功获取到数据后,dispatch发送带参数的action给注册好的reducer函数(user.jsx),修改全局state,引发从新render,数据就被刷出来啦!