Redux、MobX、Recoil、Zustand 、Jotai 对比
作为一名资深的 React 大型应用开发者,我将从架构、设计模式和原理最小实现代码等方面对比 Redux、MobX、Recoil、Zustand 和 Jotai 这几个状态管理库。
Redux:
- 架构:Redux 遵循单一数据源原则,整个应用的状态存储在一个单一的 store 中。数据流是单向的,通过 dispatch action 来触发状态更新,reducer 函数根据 action 类型和负载来计算新的状态。
- 设计模式:Redux 采用了发布-订阅模式,store 作为发布者,组件作为订阅者。当 store 中的状态发生变化时,组件会收到通知并重新渲染。
- 原理最小实现代码
function createStore(reducer) {
let state = reducer(undefined, {});
const subscribers = [];
function dispatch(action) {
state = reducer(state, action);
subscribers.forEach(subscriber => subscriber());
}
function subscribe(callback) {
subscribers.push(callback);
}
function getState() {
return state;
}
return { dispatch, subscribe, getState };
}
MobX:
- 架构:MobX 采用响应式编程的思想,通过可观察对象 (observable) 来存储状态,并自动追踪状态的变化。当可观察对象发生变化时,依赖于它的计算属性 (computed) 和反应 (reaction) 会自动更新。
- 设计模式:MobX 使用了观察者模式,可观察对象是被观察者,计算属性和反应是观察者。当可观察对象发生变化时,观察者会得到通知并执行相应的操作。
- 原理最小实现代码:
function createStore(reducer) {
let state = reducer(undefined, {});
const subscribers = [];
function dispatch(action) {
state = reducer(state, action);
subscribers.forEach(subscriber => subscriber());
}
function subscribe(callback) {
subscribers.push(callback);
}
function getState() {
return state;
}
return { dispatch, subscribe, getState };
}
MobX:
- 架构:MobX 采用响应式编程的思想,通过可观察对象 (observable) 来存储状态,并自动追踪状态的变化。当可观察对象发生变化时,依赖于它的计算属性 (computed) 和反应 (reaction) 会自动更新。
- 设计模式:MobX 使用了观察者模式,可观察对象是被观察者,计算属性和反应是观察者。当可观察对象发生变化时,观察者会得到通知并执行相应的操作。
- 原理最小实现代码:
function observable(obj) {
const observers = new Set();
return new Proxy(obj, {
set(target, key, value) {
target[key] = value;
observers.forEach(observer => observer());
return true;
},
get(target, key) {
if (typeof target[key] === 'function') {
return target[key].bind(target);
}
return target[key];
},
});
}
function autorun(reaction) {
reaction();
}
Recoil:
- 架构:Recoil 基于原子化状态 (atom) 和派生状态 (selector) 的概念。原子表示可独立更新的状态单元,选择器表示根据原子或其他选择器计算得出的状态。
- 设计模式:Recoil 采用了依赖注入的思想,通过 Provider 组件将 store 注入到组件树中,组件通过 useRecoilState 等 Hook 来访问和更新状态。
- 原理最小实现代码:
function atom(initialValue) {
let value = initialValue;
const subscribers = new Set();
function get() {
return value;
}
function set(newValue) {
value = newValue;
subscribers.forEach(subscriber => subscriber());
}
function subscribe(callback) {
subscribers.add(callback);
return () => subscribers.delete(callback);
}
return { get, set, subscribe };
}
function useRecoilState(atom) {
const [, forceUpdate] = useState(0);
useEffect(() => {
const unsubscribe = atom.subscribe(() => forceUpdate(n => n + 1));
return unsubscribe;
}, [atom]);
return [atom.get(), atom.set];
}
Zustand:
- 架构:Zustand 基于 Hook 的概念,将状态和操作状态的方法集中在一个 store 中。通过自定义 Hook 来创建和访问 store。
- 设计模式:Zustand 使用了单例模式,整个应用共享一个全局的 store 实例。通过 useStore 这个自定义 Hook 来访问 store 中的状态和方法。
- 原理最小实现代码:
function createStore(createState) {
let state;
const subscribers = new Set();
function setState(partial) {
state = { ...state, ...partial };
subscribers.forEach(subscriber => subscriber());
}
function getState() {
return state;
}
function subscribe(callback) {
subscribers.add(callback);
return () => subscribers.delete(callback);
}
state = createState(setState, getState);
return { getState, subscribe };
}
function useStore(selector) {
const store = useMemo(() => createStore(createState), []);
const [, forceUpdate] = useState(0);
useEffect(() => {
const unsubscribe = store.subscribe(() => forceUpdate(n => n + 1));
return unsubscribe;
}, [store]);
return selector(store.getState());
}
Jotai:
- 架构:Jotai 也是基于原子化概念,每个原子表示一个独立的状态单元。通过 Provider 组件将原子注入到组件树中,组件通过 useAtom 等 Hook 来访问和更新原子。
- 设计模式:Jotai 采用了依赖注入和发布-订阅模式。Provider 组件负责注入原子,原子内部维护了订阅者列表,当原子值发生变化时通知订阅者。
- 原理最小实现代码:
function atom(initialValue) {
let value = initialValue;
const subscribers = new Set();
function read() {
return value;
}
function write(newValue) {
value = newValue;
subscribers.forEach(subscriber => subscriber());
}
function subscribe(callback) {
subscribers.add(callback);
return () => subscribers.delete(callback);
}
return { read, write, subscribe };
}
function useAtom(atom) {
const [, forceUpdate] = useState(0);
useEffect(() => {
const unsubscribe = atom.subscribe(() => forceUpdate(n => n + 1));
return unsubscribe;
}, [atom]);
return [atom.read(), atom.write];
}
以上是对 Redux、MobX、Recoil、Zustand 和 Jotai 这几个状态管理库的架构、设计模式和原理最小实现代码的简要对比。每个库都有其独特的特点和适用场景:
- Redux 适用于大型应用,特别是需要进行复杂状态管理和中间件处理的场景。
- MobX 适用于中小型应用,特别是需要进行频繁的状态更新和副作用处理的场景。
- Recoil 适用于中等规模的应用,特别是需要进行状态组合和异步数据流处理的场景。
- Zustand 适用于小型到中型应用,特别是需要快速开发和简洁 API 的场景。
- Jotai 适用于各种规模的应用,特别是对性能要求较高的场景。
在实际开发中,我们需要根据具体的业务需求和团队的技术背景来选择适合的状态管理方案。同时,不同的状态管理库也可以互补,可以在同一个项目中针对不同的模块和功能选择最合适的库。