Zustand 是目前 React 生态中最流行的状态管理库之一。它以极简著称,也是我个人非常喜欢的库。 但在长期的使用中,我常常产生一种违和感:我们在一个名为“函数式”的库里,费力地模拟着面向对象。
get()来看看经典的 Zustand 写法:
const useStore = create((set, get) => ({
count: 0,
inc: () => set({ count: get().count + 1 }),
actionB: () => {
// 调用另一个 Action
get().inc();
// 获取当前状态
const val = get().count;
}
}))
仔细审视这个 get():
this**:它的作用就是访问当前实例的上下文。get(),而且它打破了 JS 引擎对 this 的自然优化。get().xxx,这并不比 this.xxx 优雅,反而增加了一层函数调用括号的视觉噪音。setset 函数的设计初衷是好的(提供类似 setState 的原子更新),但在复杂场景下,它显得不够“坦诚”:
set 隐藏了更新的细节。是合并?是替换?是深拷贝?你必须去查文档或看源码才能确定它是 "Auto Merging" 的。create 的闭包里优雅地定义私有辅助函数,往往只能写在外面,破坏了 Store 的内聚性。我们推崇函数式编程( FP ),是因为它有 纯函数、无副作用、引用透明 等数学上的美感。
但 Zustand 的 Store 定义是纯函数吗?显然不是。它是一个包含了状态( State )和行为( Action )的容器。 在计算机科学中,状态 + 行为 = 对象( Object ) 。
既然我们本质上是在构建一个对象,为什么要回避 JS 语言原生提供的、经过几十年打磨的构建对象的最佳工具——Class?
我们为了避嫌 "OOP",发明了一套 (set, get) => ({...}) 的 DSL 。这不仅牺牲了 Class 的继承、属性访问器( Getter/Setter )等高级能力,还增加了一层理解成本。
这是否是一种形式上的函数式正确,而非工程上的务实选择?
如果在 React 状态管理中,我们不再视 class 为洪水猛兽,而是承认它作为 "Model" 载体的合理性,会发生什么? 这或许值得我们深思。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.