9.你是否了解像 Zustand、Jotai 这类新兴的状态管理库?它们各自有什么特点? 副本

查看飞书原文 ↗3,838 字符
​
🎨
Zustand 和 Jotai 都是 React 生态中备受关注的新兴状态管理库,它们都由 Poimandres(一个专注于创造高质量 React 工具的组织)的开发者们创建或维护,旨在提供比传统 Redux 或 ⁠useContext + ⁠useReducer 更简洁、更现代的状态管理方案。​
有趣的是,尽管它们“师出同门”,但解决问题的哲学和路径却截然不同。我们可以将 Zustand 理解为一种“自上而下”的全局状态管理,而 Jotai 则是一种“自下而上”的原子化状态管理。​
下面,我们来分别剖析它们的特点和适用场景。​
​
Zustand:轻量、灵活的全局状态“便利店”​
​
Zustand 的核心设计思想,可以看作是 Redux 思想的现代化、轻量化实现。它借鉴了 Flux 架构中“单一数据源”和“不可变更新”的理念,但去除了大量的模板代码和繁琐的“仪式感”。​
​
它是如何工作的?​
​
Zustand 的使用非常直观。我们通过一个 create 函数来创建一个“Store”,这个 Store 本质上是一个包含了状态和更新动作的 Hook。​
​
import { create } from 'zustand';

// 1. 创建一个 Store
const useBearStore = create((set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
}));

// 2. 在任何组件中使用
function BearCounter() {
  // 通过 Selector 读取状态,只有当 `bears` 值变化时,组件才会重新渲染
  const bears = useBearStore((state) => state.bears);
  return <h1>{bears} around here ...</h1>;
}

function Controls() {
  const increasePopulation = useBearStore((state) => state.increasePopulation);
  return <button onClick={increasePopulation}>one up</button>;
}
​
核心特点:​
​
1.
极简 API 与零模板代码:没有 Actions、Reducers、Dispatch 等概念,所有状态和逻辑都封装在 create 函数中,上手成本极低。​
2.
无需 Provider:Zustand 的状态是全局的,不依赖于 React 的 Context 机制。这意味着我们不必在应用的根部用 <Provider> 包裹整个应用,可以随时在任何组件中直接调用。​
3.
基于 Selector 的性能优化:这是 Zustand 的一个关键优势。组件通过 selector 函数(例如 state => state.bears)来订阅状态的一部分。只有当这部分被订阅的状态发生变化时,组件才会触发重渲染,从而天然地避免了 useContext 在状态对象部分更新时导致所有消费者组件重渲染的问题。​
4.
灵活性高:支持中间件(Middleware),可以轻松集成 Redux DevTools、日志、持久化存储(persist)等功能。同时,它不与 React 强绑定,其核心逻辑也可以在非 React 环境中使用。​
​
适用场景:​
​
•
需要一个比 useContext 性能更好、但比 Redux 轻量得多的全局状态解决方案。​
•
管理那些本质上就是全局共享的状态,如:用户认证信息、主题(深/浅色模式)、国际化语言配置等。​
•
从 Redux 项目迁移,希望保留 Flux 思想但简化代码。​
​
​
​
​
Jotai:自下而上的原子化状态“乐高积木”​
​
Jotai 的灵感来源于 Recoil,它采用了“原子化(Atomic)”的状态管理模型。在这种模型中,状态不再是一个庞大的单一对象,而是被拆分成许多微小的、独立的状态单元,称为“Atom”。​
​
它是如何工作的?​
​
Jotai 的 API 设计巧妙地模仿了 React 的 useState,使得开发者可以无缝切换。​
​
import { atom, useAtom } from 'jotai';

// 1. 创建一个 Atom,它是一个独立的状态单元
const countAtom = atom(0);

// 我们可以创建“派生 Atom”,它的值依赖于其他 Atom
const doubleCountAtom = atom((get) => get(countAtom) * 2);

// 2. 在组件中使用,API 酷似 useState
function Counter() {
  // useAtom 返回的值和 useState 一样:[value, setValue]
  const [count, setCount] = useAtom(countAtom);
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount((c) => c + 1)}>one up</button>
    </div>
  );
}

function DoubleCounter() {
    // 读取派生 Atom 的值
    const [doubleCount] = useAtom(doubleCountAtom);
    return <p>Double: {doubleCount}</p>
}
​
核心特点:​
​
1.
原子化与自下而上:状态被组织成细粒度的 atom。这种“自下而上”的构建方式非常适合将组件内部的状态提升为可共享的全局状态,符合 React 的组件化思维。​
2.
类似 useState 的心智模型**:useAtom 的 API 设计与 useState 几乎完全一致,极大地降低了学习和使用的门槛。​
3.
精准的依赖追踪与自动优化:Jotai 会自动构建一个 Atom 之间的依赖关系图。当一个 Atom 更新时,只有精确依赖于它的其他 Atom 或使用它的组件才会重新渲染。这种优化是自动完成的,开发者无需像 Zustand 那样手动编写 selector。​
4.
强大的派生状态(Derived State):可以轻松地通过组合其他 Atom 来创建新的派生 Atom,用于处理复杂的计算或异步数据流,代码表达力非常强。​
​
适用场景:​
​
•
UI 中存在大量离散、动态、相互关联的状态,例如复杂的表单、图形编辑器、仪表盘等。​
•
希望状态管理的模式能与 React 组件的构建模式保持高度一致。​
•
当一个状态的更新逻辑需要触发一系列精确、链式的UI变化时。​
​
​
​
​
对比总结:如何选择?​
​
为了更直观地对比,我们可以用一个表格来总结:​
​
​
​
特性维度​
​
​
Zustand​
​
​
Jotai​
​
​
核心理念​
​
​
自上而下的全局 Store​
​
​
自下而上的原子化状态​
​
​
API 设计​
​
​
create 创建单一 Store,类似 Redux​
​
​
atom 创建状态单元,useAtom 类似 useState​
​
​
Provider​
​
​
无需 <Provider>​
​
​
需要 <Provider> (尽管简单场景可省略)​
​
​
性能优化​
​
​
手动:通过 Selector 订阅状态切片​
​
​
自动:通过 Atom 依赖图进行精准更新​
​
​
心智模型​
​
​
更接近 Flux/Redux​
​
​
更接近 React useState / Recoil​
​
​
适用场景​
​
​
管理明确的全局状态,作为轻量版 Redux​
​
​
管理分散、组合、相互依赖的动态状态​
​
​
​
结论:​
​
•
如果我们的需求是**“我需要一个简单好用的全局状态管理器来替代 Redux 或 useContext”**,那么 Zustand 通常是更直接、更快速的选择。它像一个功能齐全的便利店,能快速满足我们对全局状态的大多数需求。​
​
•
如果我们的应用是**由大量小型、独立且可能相互依赖的组件构成**,并且我们思考问题的方式是**“如何让这个组件的 useState 能被其他组件共享?”**,那么 Jotai 会提供一个更优雅、更符合 React 直觉的解决方案。它像一套乐高积木,让我们可以灵活地组合出任何复杂的状态结构。​
​
两者都是非常出色的库,没有绝对的优劣之分。理解它们各自的设计哲学,并根据项目需求和团队习惯做出选择,才是最关键的。​
​
本文暂未被其它文档引用