Legend-State
超高性能的 React 状态与同步库——细粒度响应式 + 内置本地优先(Local-First)持久化/同步引擎,用最少的代码构建最快的应用。
Legend-State 是基于可观察对象的 React/React Native 状态管理库,核心卖点为极致性能和内置同步引擎。通过细粒度响应式实现最小化重渲染,v3 内置乐观更新、失败重试、最小差异传输,适合本地优先和离线优先应用场景。
Legend-State
超高性能的 React 状态与同步库——细粒度响应式 + 内置本地优先(Local-First)持久化/同步引擎,用最少的代码构建最快的应用。
技术简介说明
Legend-State 是由 LegendApp 开发的 React / React Native 状态管理库,核心设计者为 Jay Meistrich。它采用可观察对象(Observable) 模型管理状态,通过 get() / set() 直接操作原始数据,无需 reducer、action、dispatcher 等样板代码。
Legend-State 的两大核心卖点:
- 极致性能:基于细粒度响应式(信号/Signal 机制),组件仅在真正依赖的数据变化时才重渲染,官方基准测试宣称"在几乎所有指标上击败其他状态库",甚至在数组交换和批量替换场景下超过原生 JavaScript。
- 内置同步引擎:v3 版本将持久化和远程同步提升为一等公民——支持乐观更新、失败重试、最小差异传输(minimal diffs),可无缝对接 Supabase、Keel、TanStack Query、fetch 等后端。
截至 2026 年 7 月,Legend-State 的 npm 包为 @legendapp/state,最新稳定版为 v2.1.15,v3 处于 beta 阶段。GitHub 星标超过 4.2k,核心库 gzip 后仅 4 kB,已在 Legend 和 Bravely 等商业产品中作为底层同步方案投入使用。
基本信息
| 项目 | 信息 |
|---|---|
| 官网 | https://legendapp.com/open-source/state/ |
| GitHub | https://github.com/LegendApp/legend-state |
| npm | https://www.npmjs.com/package/@legendapp/state |
| 最新稳定版 | v2.1.15(2024 年发布) |
| v3 Beta | v3.0.0-beta(2024 年 9 月进入 beta,持续迭代中) |
| License | MIT |
| GitHub Stars | ~4.2k |
| Bundle Size | 核心 ~4 kB(gzip) |
| TypeScript | 原生支持,源码 99.9% TypeScript,深度类型推导 |
| 主要维护者 | Jay Meistrich(@jaymeistrich),Legend / Bravely 团队 |
| 所属组织 | LegendApp(GitHub) |
| Node.js 要求 | >= 16 |
| React 要求 | >= 16.8(支持 React 18 / 19) |
快速上手
安装
# npm
npm install @legendapp/state
# yarn
yarn add @legendapp/state
# pnpm
pnpm add @legendapp/state
# bun
bun add @legendapp/state
# 安装 v3 beta
npm install @legendapp/state@beta最小示例
import { observable } from '@legendapp/state'
import { useValue } from '@legendapp/state/react'
// 1. 创建可观察状态
const store$ = observable({
count: 0,
name: 'Legend-State',
})
// 2. 在 React 组件中使用
function Counter() {
const count = useValue(store$.count)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => store$.count.set((c) => c + 1)}>+1</button>
</div>
)
}计算属性与 Actions
import { observable, observe } from '@legendapp/state'
const store$ = observable({
firstName: 'Jay',
lastName: 'Meistrich',
// 计算属性:函数自动成为 computed
get fullName() {
return `${store$.firstName.get()} ${store$.lastName.get()}`
},
items: [1, 2, 3],
// Actions:直接在 observable 上定义方法
addItem(item: number) {
store$.items.push(item)
},
})
// 监听变化
observe(() => {
console.log('Full name changed:', store$.fullName.get())
})
store$.firstName.set('John') // 触发 observe 回调启用 $ 语法糖(可选配置)
import { enable$GetSet } from '@legendapp/state/config/enable$GetSet'
enable$GetSet()
const store$ = observable({ count: 0 })
// $ 是 get() 的简写
const value = store$.count.$
// 赋值给 $ 是 set() 的简写
store$.count.$ = 42
store$.count.$++ // 支持递增核心概念与架构
1. Observable(可观察对象)
Legend-State 的核心原语是 observable(),它可以包装任意 JavaScript 值(原始类型、对象、数组、函数),返回一个响应式代理。
// 原始值
const count$ = observable(0)
// 深层对象
const store$ = observable({
user: { name: 'Jay', age: 30 },
todos: [{ id: 1, text: 'Learn Legend-State', done: false }],
})
// 读写
store$.user.name.get() // => 'Jay'
store$.user.name.set('John') // 触发所有订阅者
store$.todos[0].done.set(true) // 深层属性同样响应式2. 响应式追踪(Reactive Tracking)
Legend-State 使用基于信号的追踪系统。当在 observe() 上下文中调用 get(),会自动建立依赖关系;当被依赖的值变化时,回调自动重新执行。
import { observe } from '@legendapp/state'
// 自动追踪 store$.user.name 的依赖
const dispose = observe(() => {
console.log('Name:', store$.user.name.get())
})
store$.user.name.set('Alice') // 触发回调
dispose() // 取消订阅3. React 集成
| Hook / 组件 | 用途 |
|---|---|
useValue(obs$) | 订阅 observable 值变化,触发组件重渲染 |
useObservable(init) | 在组件内创建局部 observable |
observer(Component) | 高阶组件,自动追踪渲染中使用的 observable |
<Memo> | 细粒度渲染组件,内部节点自我更新而不触发父组件重渲染 |
For | 高效渲染 observable 数组 |
4. 同步引擎(Sync Engine)
v3 的核心架构是一个多层同步流水线:
本地修改 → 乐观更新 UI → 持久化到本地存储 → 发送到远程服务器
↑ ↓
←────── 失败重试 / 冲突解决 ←──────────────────┘
关键特性:
- 乐观更新:所有修改立即反映在本地 UI,不等网络响应
- 最小差异传输:仅发送变更的字段,节省带宽
- 无限重试:网络失败后自动排队,重连后重试
- 可插拔后端:通过
synced/syncedCrud/syncedFetch对接任意后端
核心特性
1. 零样板代码
无需 reducer、action、dispatcher、context provider。直接用 get() / set() 操作数据,就像操作普通 JavaScript 对象一样。
2. 极致性能(4kB 核心)
- 核心库 gzip 后仅 4 kB
- 细粒度响应式确保最小化重渲染
- 在数组基准测试中击败原生 JavaScript(swap / replace all rows)
- 不修改 React 内部机制,使用标准
useSyncExternalStorehook
3. 深度 TypeScript 支持
- 源码 99.9% TypeScript
- v3 类型系统从头重写,推导更精准
- 配置函数(如
enable$GetSet)自动增强类型定义
4. 内置持久化与同步
- 支持 LocalStorage、IndexedDB(Web)、MMKV、AsyncStorage、Expo SQLite(React Native)
- 远程同步插件:
syncedFetch、syncedCrud、syncedKeel、syncedSupabase - 支持乐观更新、失败重试、分页、数据转换
5. 细粒度渲染
通过 <Memo> 组件和 $value 属性绑定,实现节点级别的自我更新,父组件完全不重渲染。
6. 平台无关
同一套 API 同时支持 React(Web)、React Native、Vanilla JavaScript,无需修改原始数据结构。
7. 灵活的 Scope
状态可以是全局的(顶层 observable),也可以是组件局部的(useObservable),还可以按模块拆分多个独立 store。
8. 计算属性与 Actions
- 计算属性:在 observable 中定义 getter 函数,自动追踪依赖并缓存
- Actions:直接挂载方法到 observable,无需外部 dispatch
9. 可配置扩展
通过 enable$GetSet、enable_PeekAssign、enableReactTracking 等配置函数按需增强功能,每个配置只需调用一次。
10. 数据转换与迁移
transform 选项支持加载/保存时的数据转换,方便版本迁移、加密解密、格式适配。
生态图
LegendApp 生态
├── @legendapp/state # 核心状态管理库
│ ├── persist-plugins/
│ │ ├── local-storage # Web LocalStorage 持久化
│ │ ├── indexeddb # Web IndexedDB 持久化
│ │ ├── mmkv # React Native MMKV 持久化
│ │ ├── async-storage # React Native AsyncStorage 持久化
│ │ └── expo-sqlite # React Native Expo SQLite 持久化
│ ├── sync-plugins/
│ │ ├── fetch # 基于 fetch 的远程同步
│ │ └── crud # CRUD 后端同步
│ ├── config/
│ │ ├── enable$GetSet # $ 语法糖
│ │ ├── enable_PeekAssign # _ 静默读写
│ │ └── enableReactTracking # React 追踪警告
│ └── react/ # React hooks(useValue, useObservable 等)
│
├── @legendapp/list # 高性能列表组件(Legend-List)
├── @legendapp/motion # 动画工具
├── Legend Kit # UI 组件库
├── Keel # 后端服务(官方推荐的同步后端之一)
└── Bravely # 商业应用(使用 Legend-State 作为底层同步方案)
后端集成
| 后端 / 服务 | 集成方式 |
|---|---|
| Supabase | 官方教程 + syncedCrud 插件 |
| Keel | syncedKeel 内置插件 |
| TanStack Query | 可作为数据源对接 |
| 任意 REST API | syncedFetch 插件 |
| 自定义后端 | 基于 synced() 封装 |
适用场景
1. 本地优先(Local-First)应用
Legend-State 的同步引擎天然适合离线优先场景:数据先写本地,联网后自动同步,断网时不丢失任何操作。
2. React Native 移动应用
内置 MMKV / AsyncStorage / Expo SQLite 持久化插件,配合 Legend-List 高性能列表组件,是 React Native 应用的状态管理优选方案。
3. 需要实时同步的协作应用
如在线文档、看板、聊天工具等——subscribe 回调 + retrySync 可实现接近实时的多端同步。
4. 高频更新的大数据列表
Legend-State 在数组操作基准测试中表现优异,适合渲染数千条数据的表格、时间线、Feed 流。
5. 追求极致性能的应用
如果你的应用对渲染性能敏感(如动画、图表、仪表盘),Legend-State 的细粒度响应式可以将重渲染降到最低。
6. 需要持久化的 PWA / SPA
LocalStorage / IndexedDB 插件开箱即用,无需额外集成 Redux Persist 或 Zustand persist middleware。
7. 全栈 TypeScript 项目
深度类型推导确保前后端数据结构一致,synced 的 transform 选项处理序列化/反序列化差异。
开发与工程化
项目结构
legend-state/
├── src/
│ ├── index.ts # 核心导出(observable, observe, get, set)
│ ├── react/ # React 集成(hooks, components)
│ ├── persist-plugins/ # 持久化插件
│ ├── sync-plugins/ # 同步插件
│ └── config/ # 配置函数
├── tests/ # 测试套件
├── package.json # 版本 2.1.15 / v3 beta
└── CHANGELOG.md # 版本变更记录
构建工具
- 使用 TypeScript 编译
- 支持 ESM / CJS 双格式导出
- 提供 source map
开发命令
git clone https://github.com/LegendApp/legend-state.git
cd legend-state
pnpm install
pnpm dev # 开发模式
pnpm test # 运行测试
pnpm build # 构建版本策略
- v2 为当前稳定版(
latesttag) - v3 为 beta 版(
betatag),包含重大 API 变更和全新的同步引擎 - 提供从 v2 到 v3 的迁移指南
性能与安全
性能
Legend-State 的性能优势来源于三个层面:
| 层面 | 机制 |
|---|---|
| 追踪精度 | 基于信号的依赖追踪,精确到单个属性级别 |
| 渲染控制 | <Memo> 组件 + $value 绑定,实现节点级自我更新 |
| 同步效率 | 仅传输 minimal diffs,减少网络带宽消耗 |
官方宣称:
- 在 "swap" 和 "replace all rows" 基准测试中击败原生 JavaScript
- 支持包含数十万条目的文档而不会产生明显性能损耗
- 核心库仅 4 kB,远小于 Redux + Redux Toolkit 等方案
安全
- 防止意外修改:Legend-State 阻止直接变量赋值(如
store$.count = 5会报错),必须通过set()修改,确保所有变更都经过响应式系统 - 不修改 React 内部:使用标准
useSyncExternalStorehook,不依赖 React 私有 API,不会因 React 版本升级而崩溃 - 类型安全:TypeScript 严格模式下,非法属性访问和类型不匹配的赋值会在编译期报错
已知兼容性问题
- v3 beta 与 React Compiler 存在兼容性问题(Issue #477),2025 年 2 月报告
- 不使用不可变数据(immutability),部分标准 React API(如
React.memo的浅比较)可能不如预期工作
技术对比
与主流 React 状态库对比
| 特性 | Legend-State | Zustand | MobX | Jotai | Redux Toolkit |
|---|---|---|---|---|---|
| 核心体积 | ~4 kB | ~1.1 kB | ~16 kB | ~4 kB | ~10 kB |
| 状态模型 | Observable(响应式代理) | Single Store(不可变) | Observable(响应式代理) | Atom(原子化) | Single Store(不可变) |
| 样板代码 | 极少 | 少 | 中等 | 极少 | 多 |
| 内置持久化 | ✅ 原生支持 | 需 middleware | 需 plugin | 需 middleware | 需 redux-persist |
| 内置远程同步 | ✅ 内置同步引擎 | ❌ | ❌ | ❌ | ❌ |
| 细粒度渲染 | ✅ 信号级 | 选择器级别 | ✅ Proxy 级 | ✅ 原子级 | useSelector 级别 |
| Local-First 支持 | ✅ 一等公民 | ❌ | ❌ | ❌ | ❌ |
| React Native 支持 | ✅ 优秀(多种持久化插件) | ✅ 良好 | ✅ 良好 | ✅ 良好 | ✅ 良好 |
| TypeScript 支持 | ✅ 深度推导 | ✅ 良好 | ✅ 良好 | ✅ 良好 | ✅ 良好 |
| 学习曲线 | 中等 | 低 | 中高 | 低 | 中高 |
| 社区规模 | 4.2k ★ | 48k+ ★ | 27k+ ★ | 21k+ ★ | 68k+ ★ |
| 生态成熟度 | 中等 | 成熟 | 成熟 | 成熟 | 非常成熟 |
选型建议
- 选 Legend-State:如果你需要内置的 Local-First 同步 + 持久化,或者对渲染性能有极致要求,特别是 React Native 项目
- 选 Zustand:如果你只需要一个轻量、简单、经过大规模验证的全局状态管理
- 选 MobX:如果你已经在使用响应式编程范式,或者需要丰富的 DevTools
- 选 Jotai:如果你偏好原子化模型、需要灵活的组合式状态
- 选 Redux Toolkit:如果你需要最成熟的生态、最多的中间件、最强的 DevTools
最佳实践
1. 状态建模
// ✅ 推荐:将相关状态组织在一个 observable 中
const userStore$ = observable({
profile: { name: '', email: '' },
preferences: { theme: 'dark', language: 'zh-CN' },
isAuthenticated: false,
})
// ❌ 避免:过度拆分为过多小 observable
const name$ = observable('')
const email$ = observable('')
const theme$ = observable('dark')
// ... 难以管理2. 持久化配置
// ✅ 推荐:在应用入口统一配置持久化插件
import { configureSynced, syncedCrud } from '@legendapp/state/sync'
import { ObservablePersistLocalStorage } from '@legendapp/state/persist-plugins/local-storage'
const syncWithStorage = configureSynced(syncedCrud, {
persist: { plugin: ObservablePersistLocalStorage },
})
// 然后在各处复用
const todos$ = observable(syncWithStorage({
list: () => fetchTodos(),
create: (item) => createTodo(item),
update: (item) => updateTodo(item),
persist: { name: 'todos' },
}))3. 细粒度渲染
// ✅ 推荐:使用 <Memo> 实现节点级更新
import { Memo } from '@legendapp/state/react'
function TodoItem({ todo$ }: { todo$: Observable<{ text: string; done: boolean }> }) {
return (
<Memo>
<li>
<span>{todo$.text.get()}</span>
<input
type="checkbox"
checked={todo$.done.get()}
onChange={(e) => todo$.done.set(e.target.checked)}
/>
</li>
</Memo>
)
}
// ❌ 避免:在父组件中直接读取所有子属性
function TodoList() {
const todos = useValue(todos$) // 任何 todo 变化都会导致整个列表重渲染
return <ul>{todos.map(...)}</ul>
}4. 远程同步
// ✅ 推荐:使用 syncedCrud 封装 CRUD 后端
import { observable } from '@legendapp/state'
import { syncedCrud } from '@legendapp/state/sync-plugins/crud'
const users$ = observable(syncedCrud({
list: () => fetch('/api/users').then(r => r.json()),
create: (user) => fetch('/api/users', {
method: 'POST',
body: JSON.stringify(user),
}).then(r => r.json()),
update: (user) => fetch(`/api/users/${user.id}`, {
method: 'PUT',
body: JSON.stringify(user),
}).then(r => r.json()),
delete: (user) => fetch(`/api/users/${user.id}`, { method: 'DELETE' }),
persist: { name: 'users', retrySync: true },
retry: { infinite: true },
}))5. 异步持久化等待
// ✅ 推荐:等待异步持久化加载完成后再渲染
import { syncState } from '@legendapp/state'
function App() {
const isLoaded = useValue(syncState(store$).isPersistLoaded)
if (!isLoaded) return <LoadingSpinner />
return <MainApp />
}6. 避免在渲染中直接 get()
// ✅ 推荐:使用 useValue 订阅变化
function Counter() {
const count = useValue(store$.count)
return <p>{count}</p>
}
// ❌ 避免:直接 get() 不会触发重渲染
function Counter() {
const count = store$.count.get() // 不会订阅变化!
return <p>{count}</p>
}技术局限与边界
1. 社区规模较小
GitHub 星标 ~4.2k,远低于 Zustand(48k+)、Redux(68k+)。社区资源、教程、第三方中间件数量相对有限。
2. v3 仍在 Beta 阶段
v3 的同步引擎虽然功能强大,但尚未发布正式版。生产环境使用 v3 需要承担一定的稳定性风险。
3. 不可变数据(Immutability)不兼容
Legend-State 基于可变代理(mutable proxy),不使用不可变数据。这意味着:
React.memo的浅比较可能不如预期工作- 某些依赖不可变性的库(如 Redux DevTools)无法直接使用
- 需要开发者理解"可变但响应式"的范式差异
4. React Compiler 兼容性
截至 2025 年初,v3 beta 与 React Compiler 存在已知问题(Issue #477),在 React Compiler 启用时可能出现追踪失效。
5. 学习曲线
虽然核心 API 简单(observable + get + set),但同步引擎的配置选项较多(synced、syncedCrud、syncedFetch、persist、retry、transform 等),完整掌握需要一定时间。
6. 调试工具有限
相比 Redux DevTools 的丰富功能,Legend-State 的调试工具相对简陋。虽然 enableReactTracking 可以帮助发现遗漏的 useValue,但缺乏时间旅行调试、状态快照导出等高级功能。
7. 生态锁定风险
内置同步引擎虽然方便,但也意味着深度耦合 Legend-State 的数据流模型。如果未来需要迁移到其他状态库,同步逻辑的迁移成本较高。
学习资源
官方文档
- Legend-State 官方文档(v3) — 最权威的 API 参考和教程
- Getting Started — 快速上手指南
- Persist & Sync — 持久化与同步详解
- Migration Guide(v2 → v3) — 版本迁移指南
- Configuring — 配置函数说明
视频
- Legend State v3: Local first sync AND fastest React State manager! — v3 功能演示(2024 年 9 月)
- Building faster apps faster with Legend State - Jay Meistrich — 作者演讲
博客与教程
- Dynamically managing state with Legend-State(LogRocket Blog) — 深入使用教程
- Achieve fine grained reactivity in React(dev.to) — 细粒度响应式实战
- Local-first Realtime Apps with Expo and Legend-State(Supabase Blog) — Supabase + Legend-State 本地优先应用
- How to build an offline-first app using Expo & Legend State — Expo 离线优先应用教程
- Legend State V3(社区博客) — v3 设计理念解读
社区
- Legend 社区论坛 — 官方社区
- Discord — 实时交流
- GitHub Issues — Bug 报告与功能请求
- Legend-State Workshop — 官方练习仓库
中文资源
- 介绍 Legend-State 1.0(掘金) — 中文翻译的入门介绍
2026 年现状
版本状态
截至 2026 年 7 月:
- v2(稳定版):
@legendapp/[email protected],npmlatesttag,适合生产环境使用 - v3(Beta 版):自 2024 年 9 月进入 beta 以来,持续迭代中,文档站点已全面更新为 v3,但正式版尚未发布
- CLI 工具:v3 发布周期内推出了首个 CLI 工具版本
发展趋势
- Local-First 方向持续强化:v3 将同步引擎提升为核心能力,目标是成为"状态管理 + 数据同步"一体化方案
- Supabase / Expo 生态对接:官方博客发布了多篇 Supabase + Expo + Legend-State 的教程,Local-First 移动应用成为重点推广方向
- React Compiler 适配:社区已报告兼容性问题,预计未来版本会修复
- 社区增长平稳:GitHub 星标维持在 4.2k 左右,尚未出现爆发式增长,但在 React Native 和 Local-First 圈层中有稳定用户群
风险与展望
- v3 正式版发布时间不确定:beta 阶段已持续较长时间(2024.9 → 2026.7),生产环境使用需谨慎
- 竞争格局激烈:Zustand、Jotai、Valtio 等库在社区规模和生态成熟度上占据明显优势
- 差异化优势明确:内置同步引擎是 Legend-State 的独特卖点,在 Local-First 应用场景中尚无直接竞品
总结:Legend-State 是一个以性能和本地优先为卖点的 React 状态管理库。如果你正在构建需要离线支持、实时同步的 React / React Native 应用,并且愿意接受 v3 beta 的稳定性风险,Legend-State 提供的"状态管理 + 持久化 + 远程同步"一体化方案可以大幅减少胶水代码。但如果只需要传统的全局状态管理,Zustand 或 Jotai 是更成熟、社区支持更充分的选择。