TypeScript redux framework easy-peasy
Why
有一个知乎问题
你为什么不使用 TypeScript? - 绍毅的回答 - 知乎 https://www.zhihu.com/question/273619114/answer/1470574675
TS 没坑,框架没坑,TS+框架会有很多坑
redux with ts
redux + JavaScript 时可以使用 rematch, 用的比较舒服, 但切换到 ts 的时候要加上类型可太难了
createModel
需要传一个RootModel
类型, 循环依赖的感觉- 自己写的插件, (statePlugin & listenPlugin) 要加上类型可太难了. https://zhuanlan.zhihu.com/p/78741920
在研究上面 rematch ts 的时候发现了 easy-peasy
, 试用下来虽然有些小问题, 但都能解决, 能写起来比较舒服. 研究差不多了用 easy-peasy
重构了 clash-config-manager
@reduxjs/toolkit
- 官方实现, 没有啥毛病
createAsyncThunk
极其繁琐, 个人不喜欢. (主要是繁琐…)
问题
models 不见了
- 在使用 webpack + es module 的时候, webpack 会使用
defineProperty
会被easy-peasy
认为是computed
, 然后就被过滤掉了, 详见 createStore 方法第一行. - 解决办法可以在传给
createStore
之前先cloneDeep
一下
1 | const store = createStore(_.cloneDeep(models)) |
model 的写法
分开写 type 和 实现
1 | import {Action, action} from 'easy-peasy' |
- 官方文档上的写法, 是没什么毛病
- 但是 model 一旦大了, 相当费劲, 想新增一个 thunk, 得去 interface 新增类型, 然后在 todoModel 写实现
easy-peasy-decorators
1 | import {Model, Property, Action, createStore} from 'easy-peasy-decorators' |
优点
- 写起来很爽, 避免了 1 中的问题.
缺点
- decorators 因为标准未推进, 有废弃之势. (see mobx / clipanion / …) 但只要用的爽也不是大问题.
- decorators 缺少类型约束, 如 https://github.com/easypeasy-community/decorators/issues/4
- 仓库只有 9 个 commit, 而且很久没有更新了, 缺少维护, 用户群比较小.
- 试用之后不想再这个用了.
export default new (class ModelClass implements IState{})
1 | import _ from 'lodash' |
- https://github.com/magicdawn/clash-config-manager/blob/f68bb84a608485b5c69477436629557880fa975f/src/page/library-subscribe/model/index.ts#L1
- 通过
class ModelClass
将类型和实现写在一起, 避免 1 中的问题. - 通过
export default new ModelClass
导出一个 model 实例
thunk 被当成 state 处理了的问题(actions 为空)
使用 new ModelClass
这种方式传进 easy-peasy.createStore
之后, actions 都为空, 都被当成 state 来处理了. 具体原因不详.
解决办法: 在 cloneDeep 的时候将 class instance 转成 plain object
1 | import _ from 'lodash' |
Tips
useStoreDispatch().<model_namespace>.action()
可以像 rematch 一样直接使用 dispatch.xxx
useEasy
/ useEasyActions
/ useEasyState
1 | const {useStore, useStoreActions, useStoreDispatch, useStoreState} = createTypedHooks<StoreModel>() |
More
to be continued …