react18中react-thunk实现公共数据仓库的异步操作

reduxreact-redux都只能实现数据的同步修改更新,有点类似于vue中的mutation,只能做同步操作,异步的话不用actions来实现。由于在项目始终不可避免要实现的异步数据的更新,这明显不够用了。是时候引入我们的异步中间件redux-thunk

实现效果

代码实现

  • 安装redux-thunk
bash 复制代码
npm i redux-thunk
  • store/index.js
js 复制代码
import { createStore, applyMiddleware, compose } from "redux";
import { combineReducers } from "redux-immutable";
import { thunk } from "redux-thunk";

import { CounterReducer } from "./CounterReducer";

const reducers = combineReducers({
  count: CounterReducer,
});
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(reducers, composeEnhancers(applyMiddleware(thunk)));

export default store;
  • CounterReducer.js
    封装了两个异步方法,模拟数据的异步获取,然后导出供其他组件使用
js 复制代码
import { fromJS } from "immutable";
const initialState = fromJS({
  counter: 0,
  userInfo: {
    name: "John Doe",
    age: 25,
  },
});
function CounterReducer(state = initialState, action) {
  console.log("🚀 ~ CounterReducer ~ action:", action);
  switch (action.type) {
    case "ADD":
      return state.update("counter", (val) => {
        return val + 1;
      });
    case "ADD_TWO":
      return state.update("counter", (val) => {
        return val + 2;
      });
    case "DEC":
      return state.update("counter", (val) => val - 1);
    case "DEC_TWO":
      return state.update("counter", (val) => val - 2);
    case "CHANGE_NAME":
      return state.setIn(["userInfo", "name"], action.payload);
    default:
      return state;
  }
}

// async action 2s later
function handleDelayAdd() {
  return (dispatch) => {
  // 模拟异步接口
    setTimeout(() => dispatch({ type: "ADD_TWO" }), 2000);
  };
}

// async action 2s later
function handleDelayReduce() {
  return (dispatch) => {
  // 模拟异步接口
    setTimeout(() => dispatch({ type: "DEC_TWO" }), 2000);
  };
}

export { CounterReducer, handleDelayAdd, handleDelayReduce };
  • DemoB.js
    引入两个异步的方法,注意跟同步的dispatch使用方法有点区别,dispatch(handleDelayAdd())dispatch直接调用了该方法
js 复制代码
import { useSelector, useDispatch } from "react-redux";
import { Button, Space, Divider } from "antd";
import { handleDelayAdd, handleDelayReduce } from "../../store/CounterReducer";
function DemoB() {
  const count = useSelector((state) => state.getIn(["count", "counter"]));
  const userInfo = useSelector((state) => state.getIn(["count", "userInfo"]));
  const dispatch = useDispatch();
  return (
    <div>
      <p>Demo B</p>
      <div>
        <Space split={<Divider />}>
          <span>name: {userInfo.get("name")}</span>
          <span>age: {userInfo.get("age")}</span>
          <span>count:{count}</span>
        </Space>
      </div>
      <Space>
        <Button type="primary" onClick={() => dispatch({ type: "ADD" })}>
          add count
        </Button>
        <Button type="primary" danger onClick={() => dispatch({ type: "DEC" })}>
          minus count
        </Button>
        <Button type="primary" onClick={() => dispatch(handleDelayAdd())}>
          delay 2s add count
        </Button>
        <Button
          type="primary"
          danger
          onClick={() => dispatch(handleDelayReduce())}
        >
          delay 2s minus count
        </Button>
        <Button
          type="dashed"
          danger
          onClick={() => dispatch({ type: "CHANGE_NAME", payload: "张学友" })}
        >
          change name
        </Button>
      </Space>
    </div>
  );
}
export default DemoB;

这样我们就实现了在react项目中数据的异步更新。整体还是比较简单的。

总结

在这个具有副作用的action中,我们可以看出,函数内部可能极为复杂。如果需要为每一个异步操作都如此定义一个action,显然action不易维护。

action不易维护的原因:

  • action的形式不统一
  • 就是异步操作太为分散,分散在了各个action中
相关推荐
爱吃奶酪的松鼠丶2 分钟前
net mvc中使用vue自定义组件遇到的坑
前端·vue.js·mvc
小威编程16 分钟前
uni-app应用级生命周期和页面级生命周期
前端·vue.js·uni-app
喝旺仔la27 分钟前
Django知识进阶
前端·html
CL_IN40 分钟前
高效集成:聚水潭奇门至金蝶云星空的数据流自动化
java·前端·自动化
Ylucius42 分钟前
14天速成前端 ------学习日志(已完结)------ 后端程序员学习了解前端
java·开发语言·前端·vue.js·学习·状态模式·1024程序员节
真是6的不行1 小时前
Hbuilder html5+沉浸式状态栏
前端·html·html5·hbuilder
熊的猫1 小时前
如何封装一个可取消的 HTTP 请求?
前端·javascript·vue.js·网络协议·http·webpack·node.js
超雄代码狂2 小时前
AJAX入门
前端·ajax
csdn小瓯2 小时前
前端八股文第一篇
前端·原型模式
风流野趣fly2 小时前
要做消息列表的颜色切换
前端