前言

是这么回事,笔者刚入门的时候就觉得写redux太难受了。写action,写types,写reducer,然后在action和reducer中注入type,等写完一个redux,可能5分钟就过去了。但是好像又没有什么办法。

const prepare = 'profile_prepare';const success = 'profile_success';const fail = 'profile_fail';const getProfile = (id) => {  return {    [CALL_API]: {      uri: `/profile/${id}`,      method: 'GET',      types: [prepare, success, fail],    }  };};const reducer = (state = {}, action) => {    switch (action.type) {      case prepare:          return {            ...state,            loading: true,          };          break;      case success:          return {            ...state,            loading: false,            action.response,          };          break;      case fail:          return {            ...state,            loading: false,          };    }};

这种代码充斥在每一个action和reducer中。在实际项目中,可能会比这段demo更加复杂。

爆发

2018年,笔者开始尝试在项目中使用typescript,用是用上了,但是发现一个问题,那就是redux这一块的代码量增加了一倍。为什么?因为要写类型啊,reducer的类型,action的类型,各种类型都得定义。东西一多起来,整个reducer文件不堪入目。于是我就想着是否要把与业务无关的代码全部抽出来?说干就干

改革

经过几个月的打磨,总算是把代码抽出来了。对的,用面向对象的方式。
项目地址:redux-model-ts

可以这么说吧,代码减了50%,不需要再写type了。用ts的话还有100%的代码提示。

import { Model } from 'redux-model-ts';interface Response {  name: string;  age: number;}type Data = Partial<Response>;class Profile extends Model<Data> {  manage = this.actionRequest({    action: () => {      return this.get('/api/profile');    },    onSuccess: (state, action) => {      return {        ...state,        ...action.response,      };    },    meta: true,  });  protected initReducer(): Data {    return {};  }}export const profile = new Profile();

这段代码包含了哪些信息?

  • 定义一个action
  • 定义一个reducer
  • 自带loading判断 (profile.manage.useLoading())
  • action下自带reducer更新,不需要再写case
  • 一个模型能同时写多个action
  • type是内置的,已经自动对应
  • type可以通过接口取到 (profile.manage.getSuccessType())

是的,几行代码就完成了一组数据存储。不再写重复的代码,同时还有100%的提示,一旦你对reducer的操作有误,立马就报错。


没错,这是一篇软文,推荐我自己写的库。欢迎试用