19

两种状态管理模型

 3 years ago
source link: https://zhuanlan.zhihu.com/p/271170805
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

今天闲着没事,重构了 doux,内心一阵唏嘘,在这个状态管理烂大街的年代,谁能想到,曾经的我也搞过状态管理呢,接下来我认真谈一谈

鼻祖 elm

doux 的前身是 smox,也是一种 elm 的 js 替代实现,elm 首次将状态与视图概括为一个著名的等式: UI = state + effect

这个等式牛逼就牛逼在,它可以概括 90% 的场景,它主要有两点:

1.全局 state 树 
2. effect 隔离

redux 是 elm 的一个实现,它使用 reducer 去同步处理 state,使用中间件机制去实现 effect

dva 也是一个 elm 的替代实现,它使用 saga 去处理 effect...

还有 vuex,rematch,甚至我写的 smox

那个年代,大家对乐此不疲的讨论状态管理,纷纷给出不同的实现,甚至状态管理一度称为新人的处女作品没有之一

react 是另一个模型

elm 的模型是好的,我们乐意花时间去理解和研究这个模型,但是将 elm 的模型用于 react 就不太靠谱了……react 其实是另外一个模型: UI = fn(state)

这里的 fn 一般指的是 setState,或者说是组件也可以,反正这不是重点

重点是这里的 state 是局部的,每个组件都有自己的 state,react 自带一套基于组件和局部 state 的状态管理

强行将 elm 的模型套用到 react 中,是很怪异的

很久很久以后我才发现,原来两套不同的状态管理模型,很难强行套用在一起

这里不合理不是来自于这两个模型本身,而在于不同的人对两个模型的理解存在偏差,

有的人认为 elm 的模型是好的,所以项目就全部用 redux

有的人认为 react 的模型不好,就提倡不要在 react 中用 setState,比如 mobx 作者……

最终大家谁也说服不了谁,害

我提倡只使用 react 的模型

随着 hooks 的出现,组合更灵活,useContext 的使用方式也变得超级简单,所以在 react 里共享 state 已经不再是难事

context 就是简单的发布订阅,有人要说 context 会导致重复渲染,性能不好,不够精确

所以我重写了一下 doux,它使用依赖收集来 精确更新

import { observer, observable } from 'doux'
import { render } from 'react-dom'

const data = observable({ count: 0 })

const App = observer(() => (
  <div>
    <div>{data.count}</div>
    <button onClick={() => data.count++}>+</button>
  </div>
))

上面这段代码,首先 data 是全局的,然后首次渲染,根据 data.count 进行依赖收集,当 data.count 发生变化的时候,依赖它的组件就 rerender

context 就是简单的发布订阅,其实依赖收集也是发布订阅,只不过发布的时候有映射关系

无敌完美,只有俩 API,就解决了问题

大家可以看到,这个 API 长得很像 vue3 的 composition API,我们借机谈一下

composition API 的缺陷

我一直认为 composition API 不是个好东西

最大的坑是 reactive 和 ref,其实这个坑本质上是因为他们要将 data 作为局部的,然后 return 给 template 导致的

但是使用闭包进行依赖收集的机制,根本不 care 你这个 data 是局部的还是全局的

昨天写了一天 vue3,写一个嵌套表单就把自己绕进去了,toRefs 什么的,心智负担太大了

所以今天才会重写 doux,拒绝抄袭不好的东西呜呜呜

write on copy

为了保证不可变,doux 使用了类似 immer 的写时拷贝机制,不过 doux 的做法更纯粹,写的时候拷贝,取的时候先从拷贝中取

唉,用 Proxy 模拟 document,依赖收集,写时拷贝……感觉 Proxy 快被我玩坏了 emm

总结

大家在 fre 中可以使用 doux,因为 fre 没有 context,在 react 中能用 context 还是用 context

除非你真的对 doux 很感兴趣,哈哈,放一下 github 地址,欢迎 star 和 pr!

https:// github.com/yisar/doux


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK