Recoil 是 Facebook 推出的一个实验性状态管理库,专为 React 设计。它的核心理念是将状态拆分为一个个独立的原子(Atom),组件可以精确订阅它们需要的原子,当原子更新时,只有订阅了该原子的组件才会重渲染。基于原子,Recoil 提供了派生状态(Selector),用于计算衍生数据或异步获取数据,同样具备细粒度订阅特性。
核心概念
Atom
Atom 是最小的状态单元,每个 Atom 存储一个独立的值,可以被多个组件共享。当 Atom 的值发生变化时,所有订阅它的组件会自动重新渲染,无需手动通知。
import { atom } from 'recoil';
// 定义原子
export const todoListState = atom({
key: 'todoListState', // 唯一标识
default: [], // 初始值
});
在组件中读写 Atom 就像使用 useState 一样简单:
import { useRecoilState } from 'recoil';
function TodoList() {
const [todos, setTodos] = useRecoilState(todoListState);
// ...
}
Selector
Selector 是派生状态,可以基于一个或多个 Atom 或其他 Selector 计算出一个新值。当依赖的原始状态变化时,Selector 会自动重新计算,且只有订阅该 Selector 的组件才会重渲染。Selector 也支持异步逻辑。
import { selector } from 'recoil';
// 派生状态:统计待办事项数量
export const todoStatsSelector = selector({
key: 'todoStatsSelector',
get: ({ get }) => {
const todos = get(todoListState);
return {
total: todos.length,
completed: todos.filter(t => t.done).length,
active: todos.filter(t => !t.done).length,
};
},
});
组件使用 Selector 与使用 Atom 类似:
function TodoStats() {
const stats = useRecoilValue(todoStatsSelector);
return <div>已完成: {stats.completed}</div>;
}
为什么选择 Recoil?
- 细粒度渲染:组件只关注自己需要的那一部分状态,避免全局 store 变化导致的全量重渲染。
- 简洁的 API:
useRecoilState、useRecoilValue、useSetRecoilState等钩子与 React 的useState非常接近,学习成本低。 - 懒加载与异步:Selector 天然支持异步数据请求,无需额外中间件。
- 可组合性:可以将多个 Selector 组合在一起构建复杂的数据依赖图,类似电子表格的公式。
适用场景与局限性
Recoil 很适合需要细粒度状态控制、频繁更新的中等规模应用,尤其是当 Context 性能瓶颈明显或 Redux 觉得过于繁琐时。但它仍处于早期阶段,社区生态不如 Redux 成熟,对于非常大的应用,可能需要额外关注原子依赖图的组织。目前 Recoil 已停止活跃开发,新项目可考虑 Jotai 作为轻量替代,但 Recoil 的设计思路深刻影响了后续原子化状态库的演进。