一提起 React 状态管理,不少人就提也不想提。html
Redux: 1 号选手,人气最高的一个,得与 react-redux
一同使用。本身无论异步,因此常听到的什么 redux-thunk
、redux-saga
是其下属,专门擦屁股的。特色就是难用,若是按照官方文档的写法用,基本就是想死。推荐阅读:www.zhihu.com/question/33…vue
Mobx: 2 号选手,使用监听的方式,与 React 的思想背道而驰,思想有问题,流氓!react
dva: Redux 封装,使用了 redux-saga
,generator 的写法,想死。git
Rematch: Redux 封装,相似 dva,model
中分为 reducers
和 effects
,不够简洁。github
广告:因此仍是 🐤 Retalk 最简单,史上最简单的 Redux 封装,走过路过不要错过:github.com/nanxiaobei/…vuex
无论怎么说,Hooks 来了,之前的状态管理都是给之前的开发方式用的,为了对 Hooks 有点表示,也就加几个 useBlabla()
完事。redux
与 Hooks 的轻灵相比,它们都显得笨重、老态龙钟、敷衍。bash
有没有专用于 Hooks 的状态管理呢?目前尚未众望所归的,基本都是老选手搞个兼职,有点不三不四。服务器
不够革命。异步
一个是为了解决相邻组件的通讯问题。
虽然能够经过「状态提高」解决,但有两个问题:
每次子组件更新,都会触发负责下发状态的父组件的总体更新(使用 Context 也有这个问题),而后写一大堆 PureComponent
、shouldComponentUpdate
,代码还能看吗?React 设计中的糟粕写了个够,太惨。
逻辑比较多的话,都写在父组件里,代码还能看吗?根本不考虑父组件的感觉。
因此「状态提高」不是个好思路,仍是须要状态管理。
另外,状态管理最重要的一个好处,就是 ——
它能够把「与服务器交互」和「操做数据」的逻辑,从组件中提取出去,组件只用接收处理好的数据便可。这就至关于分离了个 Service 层出去,很好的开发模式。
代码逻辑分离,各司其职,组件去干组件该干的事,这才是最大的好处。
因此咱们须要状态管理。
若是一开始是从 Redux 上手,会发现它提供了一个全局的 store。而后呢?而后它也没说什么话,有什么问题就本身解决吧,我先睡了。
实际业务开发中,遇到的最多见的场景,就是须要区分不一样的「模块」,这是最基本的需求。
Vuex 比较务实,提供了 modules
的概念。
Redux 呢?固然是得靠你本身啦,咱们提供一个理念就好了,这么简单的东西,你就本身去搞吧。
若是不从 API 设计上进行规范,必然会致使无数不一样的实现。(单押 x 2)
CHAOS.
咱们须要什么样的状态管理?
咱们须要符合中国特点社会主义初级阶段国情的状态管理。
咱们须要能够划分不一样的模块,模块是独立的,同时模块间又是能够自由沟通的。
不少状态管理库只考虑了模块的「独立」,可是对「沟通」保持沉默,这是不友好的。
独立,且连通 —— 这才是模块的意义所在。
通常来讲,推荐按照基本的路由入口,划分出不一样的模块,这也是 dva 中的思路(它的文件夹干脆就叫 routes
)。
这也符合天然的思惟方式,划分路由,也就是自然的认为它们属于不一样的模块。
而每一个状态管理的模块,咱们称之为 "model",建议与路由入口组件绑定起来,每一个入口组件及其子组件,总体对应一个 model。
---A
index.jsx
model.js
---B
index.jsx
model.js
---C
index.jsx
model.js
复制代码
模块是独立的,毋庸置疑,模块模块,不独立还叫模块吗?
那模块如何沟通呢?
在组件中,能够获取到自身 model 和其它的 model,这并不难。
主要是,在 model 内部,自身各个方法须要互相调用,同时须要拿到其它 model 的数据和方法,这才是沟通的意义。
还得足够简单。
这样才是一个良好而完全的设计。
最直接的,咱们但愿在组件中,经过 Hooks 去访问到某个 model。
const { someStateInA, someActionInA } = useModel(a);
// or
const { someStateInA, someActionInA, someStateInB, someActionInB } = useModels(a, b);
复制代码
useModel()
中传入某个 model,这样设计的话,须要哪一个 model,就得在组件中引入 model 的文件,不够自由,不能依赖于必须去引入文件。
只要操做麻烦,代码写的变多,就不是好的设计。
另外 Hooks 是为了让代码更清晰,咱们不能像 Mobx 同样,违背总体系统的设计哲学。
因此 model 获取最好是分开的,useModels(a, b)
一次性引入多个 model 的方式,不够清晰。
不能依赖文件,引入得清晰,因此:
const { someStateInA, someActionInA } = useModel('a');
const { someStateInB, someActionInB } = useModel('b');
复制代码
依赖一个字符串,这样就不须要在每一个组件中引入文件。useModel()
只能访问一个 model,代码足够清晰。
这是咱们须要的设计。
一个 model 整体来讲能够分为两大块,数据(state
)和操做数据的方法(reducers
、effects
)。
reducers
与 effects
,或者 Vuex 中的 mutations
与 actions
,是为了区分直接改变和异步操做,同步函数和异步函数。不够简洁,能不能合并成一个?
答案能够的,咱们称之为 actions
。
更新 state 的方法,直接注入 model 中,因此一个 action 能够是同步也能够是异步,它只是被当作函数来调用。
因而,model 中分为两块就好:
exports default {
state: {},
actions: {},
}
复制代码
model 沟通,主要是实如今 action 中去访问其它须要的东西。
自由而无限制的沟通。
一个 action 中须要访问到如下:1. 自身 state,2. 自身 action,3. 其它模块 state,4. 其它模块 action,5. 自身 state updater。
简化一下,就是须要访问:1. 自身 model,2. 其它 model,3. 自身 state updater。
再简化一下:1. model,2. 自身 state updater。
因此其实只须要两个方法:getModel()
和 setState()
。
getModel()
获取自身,getModel('other')
获取其它。
如何拿到这两个方法呢?
经过 this
访问。但咱们是给 Hooks 设计状态管理,Hooks 就是为了抛弃 this
,仍是那句话 —— 不能违背系统的设计哲学。
Vuex 中,是在函数第一个参数注入 context,调用时比较反直觉,放弃这种方式。
model 文件中 import 方法进来,太麻烦了,只要操做麻烦,代码写的变多,就不是好的设计。
因此惟一的方式(Rematch 的设计中也能看到),就是在参数中注入方法。
也就是把 actions
变为一个函数:
exports default {
state: {},
actions: ({ getModel, setState }) => ({
someAction() {
const { someState, someOtherAction } = getModel();
}
}),
}
复制代码
这里考虑到一个美学问题,getModel()
由于不少 action 都会用到,而实际写出来时,由于 l
高度的问题,又比较丑,因此就把 API 简化为了 model()
。
model()
获取自身,model('other')
获取其它。
因而,flooks,福禄克斯,诞生了:
🍸 flooks → github.com/nanxiaobei/…
import { setModel, useModel } from 'flooks';
const a = {
state: {},
actions: ({ model, setState }) => ({
someAction() {
const { someState, someOtherAction } = model();
...
setState(payload);
}
}),
}
setModel('a', a);
function A() {
cosnt { someState, someAction } = useModel('a');
return (
...
)
}
复制代码
自然的模块化支持。
只有两个 API,setModel()
和 useModel()
。
加上 actions
的两个参数,model()
和 setState()
,就这么多。
足够简单,足够实现一切。
去中心化,去中心化,去中心化。
一切都为了更简单的开发。
再不须要顶层分发 store,不须要 store 文件夹或 store.js 文件。
无需顶层 createStore()
,无需顶层 Provider
。
注册 model 时,无需先在中心化文件中引入 model,自身文件夹内就能够搞定一切。
直接用 setModel()
把组件和 model 链接起来,就这么简单。
模块化,积木同样组合,简洁,灵活,这是咱们的理念。
每一个组件和 model 构成一个自组织,同时它们又能够访问到世界各地。它们不用去有关部门报道,就能在世界的任何角落相遇。
这是咱们的哲学:独立,自由,个体,世界。