"造轮子记":设计并实现一个简易版状态管理库

67 阅读8分钟

引言

在现代前端开发中,状态管理是一个核心问题。随着应用规模的扩大,全局状态管理变得越来越重要。Redux、Vuex、MobX和Zustand等库各有千秋,但它们都在尝试解决同一个问题:如何高效地管理和同步应用状态。今天,我们将从零开始,实现一个简洁而强大的状态管理库——StateFlow。

核心设计理念

StateFlow 基于以下核心理念:

  1. 单一数据源:所有状态存储在一个中央store中
  2. 不可变数据:状态修改通过创建新对象实现,保证状态追踪
  3. 发布订阅模式:组件订阅状态变化,实现精确更新
  4. 响应式API:简洁直观的接口,降低使用成本

我们将融合Redux的可预测性和Zustand的简洁API,同时借鉴MobX的响应式思想。

实现核心功能

首先,定义我们的基础API:

// stateflow.ts
type Listener = () => void;
type Selector<T, S> = (state: T) => S;

interface StateFlow<T> {
  getState: () => T;
  setState: (partial: Partial<T> | ((state: T) => Partial<T>)) => void;
  subscribe: (listener: Listener) => () => void;
  select: <S>(selector: Selector<T, S>) => StateFlow<S>;
}

function createStore<T extends object>(initialState: T): StateFlow<T> {
  let state = { ...initialState };
  const listeners = new Set<Listener>();
  
  const getState = () => state;
  
  const setState = (partial: Partial<T> | ((state: T) => Partial<T>)) => {
    const nextPartial = typeof partial === 'function' 
      ? partial(state) 
      : partial;
    
    const nextState = { ...state, ...nextPartial };
    if (!Object.is(nextState, state)) {
      state = nextState;
      listeners.forEach(listener => listener());
    }
  };
  
  const subscribe = (listener: Listener) => {
    listeners.add(listener);
    return () => listeners.delete(listener);
  };
  
  const select = <S>(selector: Selector<T, S>): StateFlow<S> => {
    let currentValue = selector(state);
    
    return {
      getState: () => selector(state),
      setState: () => { throw new Error('Cannot set state of a selector'); },
      subscribe: (listener: Listener) => {
        const unsubscribe = subscribe(() => {
          const nextValue = selector(state);
          if (!Object.is(currentValue, nextValue)) {
            currentValue = nextValue;
            listener();
          }
        });
        return unsubscribe;
      },
      select: <R>(nextSelector: Selector<S, R>) => {
        const composedSelector = (s: T) => nextSelector(selector(s));
        return select(composedSelector);
      }
    };
  };

  return { getState, setState, subscribe, select };
}

React集成

为了方便在React项目中使用,我们实现一个自定义Hook:

// react-stateflow.ts
import { useEffect, useState, useRef } from 'react';
import { StateFlow, Selector } from './stateflow';

export function useStore<T, S = T>(
  store: StateFlow<T>,
  selector?: Selector<T, S>
): S {
  const selectedStore = selector ? store.select(selector) : store as unknown as StateFlow<S>;
  const [state, setState] = useState<S>(() => selectedStore.getState());
  
  // 使用useRef避免不必要的重新订阅
  const storeRef = useRef(selectedStore);
  
  useEffect(() => {
    // 仅当store或selector变更时才更新storeRef
    storeRef.current = selectedStore;
    
    // 初始化时同步一次状态,避免闭包问题
    setState(selectedStore.getState());
    
    const unsubscribe = selectedStore.subscribe(() => {
      setState(storeRef.current.getState());
    });
    
    return unsubscribe;
  }, [selectedStore]);
  
  return state;
}

高级功能:中间件机制

// middleware.ts
type NextFunction<T> = (partial: Partial<T> | ((state: T) => Partial<T>)) => void;
type MiddlewareAPI<T> = {
  getState: () => T;
  setState: NextFunction<T>;
};

type Middleware<T> = (
  api: MiddlewareAPI<T>
) => (next: NextFunction<T>) => NextFunction<T>;

function applyMiddleware<T extends object>(
  createStoreFunc: typeof createStore,
  ...middlewares: Middleware<T>[]
) {
  return (initialState: T): StateFlow<T> => {
    const store = createStoreFunc(initialState);
    let dispatch = store.setState;
    
    const middlewareAPI: MiddlewareAPI<T> = {
      getState: store.getState,
      setState: (action) => dispatch(action)
    };
    
    const chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = chain.reduce(
      (prev, current) => current(prev),
      store.setState
    );
    
    return {
      ...store,
      setState: dispatch
    };
  };
}

异步操作支持

// async.ts
type AsyncAction<T> = (
  setState: (partial: Partial<T> | ((state: T) => Partial<T>)) => void,
  getState: () => T
) => Promise<void> | void;

// 扩展store以支持异步操作
function enhanceStore<T extends object>(store: StateFlow<T>) {
  const { setState, getState } = store;
  
  const asyncDispatch = (action: AsyncAction<T>) => {
    return action(setState, getState);
  };
  
  return {
    ...store,
    asyncDispatch
  };
}

// 使用示例
// asyncDispatch(async (setState, getState) => {
//   setState({ loading: true });
//   try {
//     const data = await fetchData();
//     setState({ data, loading: false });
//   } catch (error) {
//     setState({ error, loading: false });
//   }
// });

时间旅行与DevTools集成

// devtools.ts
interface Action<T> {
  type: string;
  payload?: Partial<T> | ((state: T) => Partial<T>);
  timestamp: number;
}

interface TimeTravel<T> {
  getHistory: () => T[];
  getActionHistory: () => Action<T>[];
  goTo: (index: number) => void;
  undo: () => void;
  redo: () => void;
  getCurrentIndex: () => number;
}

const devTools = <T extends object>(store: StateFlow<T>) => {
  let actionIdx = -1;
  const actionHistory: Action<T>[] = [];
  const stateHistory: T[] = [store.getState()];
  
  const originalSetState = store.setState;
  
  const enhancedSetState = (partial: Partial<T> | ((state: T) => Partial<T>)) => {
    const action: Action<T> = {
      type: typeof partial === 'function' ? 'FUNCTION_ACTION' : 'UPDATE',
      payload: partial,
      timestamp: Date.now()
    };
    
    // 调用原始setState
    originalSetState(partial);
    
    // 截断历史记录,添加新状态
    actionHistory.splice(actionIdx + 1);
    stateHistory.splice(actionIdx + 1);
    
    actionHistory.push(action);
    stateHistory.push(store.getState());
    actionIdx++;
  };
  
  // 时间旅行API
  const timeTravel: TimeTravel<T> = {
    getHistory: () => [...stateHistory],
    getActionHistory: () => [...actionHistory],
    getCurrentIndex: () => actionIdx,
    goTo: (index: number) => {
      if (index >= 0 && index < stateHistory.length) {
        actionIdx = index;
        originalSetState(() => stateHistory[index]);
      }
    },
    undo: () => {
      if (actionIdx > 0) {
        timeTravel.goTo(actionIdx - 1);
      }
    },
    redo: () => {
      if (actionIdx < stateHistory.length - 1) {
        timeTravel.goTo(actionIdx + 1);
      }
    }
  };
  
  return { 
    ...store, 
    setState: enhancedSetState,
    timeTravel 
  };
};

使用示例

// App.tsx
import React from 'react';
import { createStore } from './stateflow';
import { useStore } from './react-stateflow';
import { applyMiddleware } from './middleware';
import { devTools } from './devtools';
import { enhanceStore } from './async';

// 定义应用状态
interface AppState {
  count: number;
  todos: { id: number; text: string; completed: boolean }[];
  theme: 'light' | 'dark';
  loading: boolean;
  error: Error | null;
}

// 创建初始状态
const initialState: AppState = {
  count: 0,
  todos: [],
  theme: 'light',
  loading: false,
  error: null
};

// 创建日志中间件
const logger: Middleware<AppState> = store => next => action => {
  console.log('before state:', store.getState());
  console.log('action:', action);
  const result = next(action);
  console.log('after state:', store.getState());
  return result;
};

// 创建性能监控中间件
const perfMonitor: Middleware<AppState> = store => next => action => {
  const start = performance.now();
  const result = next(action);
  const end = performance.now();
  console.log(`Action took ${end - start}ms to process`);
  return result;
};

// 创建增强版store
const createStoreWithMiddleware = applyMiddleware(createStore, logger, perfMonitor);
const baseStore = createStoreWithMiddleware(initialState);
const store = enhanceStore(devTools(baseStore));

// 计数器组件
function Counter() {
  const count = useStore(store, state => state.count);
  
  return (
    <div>
      <h2>计数器: {count}</h2>
      <button onClick={() => store.setState({ count: count + 1 })}>
        增加
      </button>
      <button onClick={() => store.setState({ count: count - 1 })}>
        减少
      </button>
    </div>
  );
}

// Todo列表组件
function TodoList() {
  const todos = useStore(store, state => state.todos);
  const [text, setText] = React.useState('');
  
  const addTodo = () => {
    if (!text.trim()) return;
    
    store.setState(state => ({
      todos: [
        ...state.todos,
        {
          id: Date.now(),
          text,
          completed: false
        }
      ]
    }));
    
    setText('');
  };
  
  const toggleTodo = (id: number) => {
    store.setState(state => ({
      todos: state.todos.map(todo =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    }));
  };
  
  // 异步加载示例
  const loadSampleTodos = () => {
    store.asyncDispatch(async (setState) => {
      setState({ loading: true, error: null });
      try {
        // 模拟API请求
        await new Promise(resolve => setTimeout(resolve, 1000));
        
        setState(state => ({
          todos: [
            ...state.todos,
            { id: Date.now(), text: '示例任务1', completed: false },
            { id: Date.now() + 1, text: '示例任务2', completed: true }
          ],
          loading: false
        }));
      } catch (error) {
        setState({ loading: false, error: error instanceof Error ? error : new Error('未知错误') });
      }
    });
  };
  
  // 获取加载状态
  const loading = useStore(store, state => state.loading);
  
  return (
    <div>
      <h2>待办事项</h2>
      <div style={{ display: 'flex', gap: '10px', marginBottom: '10px' }}>
        <input
          value={text}
          onChange={e => setText(e.target.value)}
          placeholder="添加新任务"
          disabled={loading}
        />
        <button onClick={addTodo} disabled={loading}>添加</button>
        <button onClick={loadSampleTodos} disabled={loading}>
          {loading ? '加载中...' : '加载示例'}
        </button>
      </div>
      
      {loading && <div>加载中...</div>}
      
      <ul style={{ minHeight: '100px' }}>
        {todos.map(todo => (
          <li
            key={todo.id}
            style={{ 
              textDecoration: todo.completed ? 'line-through' : 'none',
              cursor: 'pointer',
              padding: '5px 0'
            }}
            onClick={() => toggleTodo(todo.id)}
          >
            {todo.text}
          </li>
        ))}
        {todos.length === 0 && !loading && (
          <li style={{ color: '#999', fontStyle: 'italic' }}>暂无任务</li>
        )}
      </ul>
    </div>
  );
}

// 主题切换组件
function ThemeSwitcher() {
  const theme = useStore(store, state => state.theme);
  
  return (
    <button
      onClick={() => 
        store.setState({ theme: theme === 'light' ? 'dark' : 'light' })
      }
      style={{
        padding: '8px 16px',
        borderRadius: '4px',
        backgroundColor: theme === 'light' ? '#333' : '#fff',
        color: theme === 'light' ? '#fff' : '#333',
        border: 'none',
        cursor: 'pointer'
      }}
    >
      当前主题: {theme === 'light' ? '☀️' : '🌙'}
    </button>
  );
}

// 时间旅行控制器
function TimeTravel() {
  const [history, setHistory] = React.useState(store.timeTravel.getHistory());
  const currentIndex = store.timeTravel.getCurrentIndex();
  
  // 监听状态变化,更新历史记录
  React.useEffect(() => {
    const unsubscribe = store.subscribe(() => {
      setHistory([...store.timeTravel.getHistory()]);
    });
    return unsubscribe;
  }, []);
  
  return (
    <div>
      <h2>时间旅行</h2>
      <div style={{ display: 'flex', gap: '10px', marginBottom: '10px' }}>
        <button 
          onClick={() => store.timeTravel.undo()}
          disabled={currentIndex <= 0}
        >
          ⏮️ 撤销
        </button>
        <button 
          onClick={() => store.timeTravel.redo()}
          disabled={currentIndex >= history.length - 1}
        >
          ⏭️ 重做
        </button>
      </div>
      
      <div>
        <h3>历史状态: ({currentIndex + 1}/{history.length})</h3>
        <ul style={{ 
          height: '200px', 
          overflow: 'auto',
          border: '1px solid #ccc',
          borderRadius: '4px',
          padding: '8px',
          margin: '0'
        }}>
          {history.map((state, index) => (
            <li 
              key={index}
              style={{ 
                padding: '4px 8px',
                backgroundColor: index === currentIndex ? '#e6f7ff' : 'transparent',
                borderRadius: '4px',
                cursor: 'pointer',
                marginBottom: '4px'
              }}
            >
              <div onClick={() => store.timeTravel.goTo(index)}>
                状态 #{index}
                {index === currentIndex && ' (当前)'}
              </div>
              <pre style={{
                fontSize: '12px',
                overflow: 'hidden',
                maxHeight: index === currentIndex ? 'none' : '60px'
              }}>
                {JSON.stringify(state, null, 2)}
              </pre>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

// 可视化状态图表组件
function StateVisualizer() {
  const count = useStore(store, state => state.count);
  const todos = useStore(store, state => state.todos);
  const completedTodos = todos.filter(todo => todo.completed).length;
  const pendingTodos = todos.length - completedTodos;
  
  return (
    <div>
      <h2>状态可视化</h2>
      <div style={{ 
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
        marginTop: '10px'
      }}>
        <div>
          <div>计数器值: {count}</div>
          <div style={{ 
            height: '20px',
            width: `${Math.min(Math.abs(count) * 10, 100)}%`,
            backgroundColor: count >= 0 ? '#52c41a' : '#f5222d',
            borderRadius: '4px',
            transition: 'all 0.3s ease'
          }} />
        </div>
        
        <div>
          <div>待办项: {todos.length} (已完成: {completedTodos}, 待完成: {pendingTodos})</div>
          {todos.length > 0 && (
            <div style={{ display: 'flex', height: '20px', borderRadius: '4px', overflow: 'hidden' }}>
              <div style={{ 
                flex: completedTodos,
                backgroundColor: '#52c41a',
                transition: 'all 0.3s ease'
              }} />
              <div style={{ 
                flex: pendingTodos,
                backgroundColor: '#faad14',
                transition: 'all 0.3s ease'
              }} />
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// 主应用
function App() {
  const theme = useStore(store, state => state.theme);
  const error = useStore(store, state => state.error);
  
  return (
    <div style={{
      padding: '20px',
      backgroundColor: theme === 'light' ? '#fff' : '#222',
      color: theme === 'light' ? '#222' : '#fff',
      minHeight: '100vh',
      transition: 'all 0.3s ease'
    }}>
      <h1>StateFlow 演示</h1>
      <ThemeSwitcher />
      <hr />
      
      {error && (
        <div style={{ 
          padding: '10px',
          backgroundColor: '#fff2f0',
          borderRadius: '4px',
          marginBottom: '20px',
          color: '#f5222d',
          border: '1px solid #ffccc7'
        }}>
          错误: {error.message}
        </div>
      )}
      
      <div style={{ 
        display: 'grid',
        gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
        gap: '20px'
      }}>
        <div>
          <Counter />
          <TodoList />
          <StateVisualizer />
        </div>
        <TimeTravel />
      </div>
    </div>
  );
}

export default App;

性能优化

StateFlow 通过以下机制实现性能优化:

  1. 选择器记忆化:避免不必要的重新计算和渲染
  2. 浅比较:使用 Object.is 进行状态比较,减少不必要的更新
  3. 批量更新:结合 React 的批处理机制
  4. 选择性渲染:只有当关心的部分状态变化时才触发更新

可以进一步增强:

// optimized-selectors.ts
function createSelector<T, R>(
  selectors: ((state: T) => any)[],
  combiner: (...args: any[]) => R,
  equalityFn: (a: R, b: R) => boolean = Object.is
): (state: T) => R {
  let lastInputs: any[] | undefined;
  let lastResult: R | undefined;
  
  return (state: T) => {
    const inputs = selectors.map(selector => selector(state));
    
    if (
      !lastInputs || 
      inputs.length !== lastInputs.length ||
      inputs.some((input, i) => !Object.is(input, lastInputs![i]))
    ) {
      const newResult = combiner(...inputs);
      
      // 允许自定义相等检查函数
      if (!lastResult || !equalityFn(lastResult, newResult)) {
        lastResult = newResult;
      }
    }
    
    lastInputs = inputs;
    return lastResult as R;
  };
}

// 批量处理状态更新的工具函数
function batch<T>(store: StateFlow<T>, fn: () => void): void {
  const originalSetState = store.setState;
  let batching = false;
  let pendingState: Partial<T> = {};
  
  store.setState = (partial) => {
    if (typeof partial === 'function') {
      // 对于函数类型,立即执行以获取实际更新
      const partialState = partial(store.getState());
      pendingState = { ...pendingState, ...partialState };
    } else {
      pendingState = { ...pendingState, ...partial };
    }
  };
  
  try {
    batching = true;
    fn();
  } finally {
    batching = false;
    store.setState = originalSetState;
    if (Object.keys(pendingState).length > 0) {
      originalSetState(pendingState);
    }
  }
}

持久化方案

// persistence.ts
type StorageEngine = {
  getItem: (key: string) => string | null | Promise<string | null>;
  setItem: (key: string, value: string) => void | Promise<void>;
};

interface PersistOptions<T> {
  key: string;
  storage?: StorageEngine;
  whitelist?: (keyof T)[];
  blacklist?: (keyof T)[];
  serialize?: (data: any) => string;
  deserialize?: (data: string) => any;
  throttle?: number;
}

async function persistStore<T>(
  store: StateFlow<T>,
  options: PersistOptions<T>
) {
  const {
    key,
    storage = localStorage,
    whitelist,
    blacklist,
    serialize = JSON.stringify,
    deserialize = JSON.parse,
    throttle = 0
  } = options;
  
  // 过滤状态,只保留需要持久化的部分
  const filterState = (state: T): Partial<T> => {
    if (whitelist) {
      return Object.fromEntries(
        whitelist.map(k => [k, state[k]])
      ) as Partial<T>;
    } else if (blacklist) {
      const result = { ...state };
      blacklist.forEach(k => delete result[k as keyof T]);
      return result;
    }
    return state;
  };
  
  // 初始化:从存储中恢复状态
  try {
    const savedState = await Promise.resolve(storage.getItem(key));
    if (savedState) {
      const parsedState = deserialize(savedState);
      store.setState(parsedState);
    }
  } catch (e) {
    console.error('Failed to restore state from storage:', e);
  }
  
  // 节流函数
  let timeout: number | null = null;
  const saveState = () => {
    try {
      const state = filterState(store.getState());
      const serializedState = serialize(state);
      Promise.resolve(storage.setItem(key, serializedState));
    } catch (e) {
      console.error('Failed to persist state to storage:', e);
    }
  };
  
  // 订阅变更:将状态保存到存储
  store.subscribe(() => {
    if (throttle === 0) {
      saveState();
    } else if (timeout === null) {
      timeout = window.setTimeout(() => {
        saveState();
        timeout = null;
      }, throttle);
    }
  });
  
  // 添加手动持久化方法
  return {
    ...store,
    persist: saveState
  };
}

与React Concurrent Mode的协作

// concurrent.ts
import { startTransition, useTransition } from 'react';

function concurrentStore<T extends object>(initialState: T) {
  const store = createStore(initialState);
  const originalSetState = store.setState;
  
  store.setState = (partial) => {
    startTransition(() => {
      originalSetState(partial);
    });
  };
  
  return store;
}

// 与React 18的useTransition结合使用的Hook
export function useTransitionStore<T, S = T>(
  store: StateFlow<T>,
  selector?: Selector<T, S>
): [S, boolean, (updater: Partial<T> | ((state: T) => Partial<T>)) => void] {
  const [isPending, startStateTransition] = useTransition();
  const state = useStore(store, selector);
  
  const setTransitionState = (updater: Partial<T> | ((state: T) => Partial<T>)) => {
    startStateTransition(() => {
      store.setState(updater);
    });
  };
  
  return [state, isPending, setTransitionState];
}

不同设计模式对比

模式优点缺点适用场景
Flux/Redux单向数据流,可预测性强,便于调试样板代码多,初学者难以掌握大型应用,多人协作,需要高可追踪性
MobX响应式编程,代码简洁,自动追踪依赖黑盒机制,调试复杂,可能过度优化中小型应用,追求开发效率
ZustandAPI简洁,无需Context Provider,模块化缺少内置中间件,生态相对较小轻量级应用,React hooks用户
Recoil原子化管理,良好并发支持,细粒度控制API复杂,需要RecoilRoot包装需要细粒度控制的复杂UI应用
Jotai超轻量,原子化设计,组合性强复杂场景需要额外抽象原子化状态管理,轻量级应用
StateFlow简洁API,灵活中间件,高性能选择器需要自行处理一些边界情况希望兼顾简洁与灵活的应用

StateFlow 结合了Flux的可预测性和Zustand的简洁性,同时通过选择器机制和中间件提供了极大的灵活性。

调试工具可视化

// devtools-visualizer.ts
// 可以与主流浏览器开发者工具集成的可视化调试工具

class StateFlowDevTools<T> {
  private store: StateFlow<T>;
  private connected: boolean = false;
  private actionLog: {
    type: string;
    payload: any;
    timestamp: number;
    stateBefore: T;
    stateAfter: T;
  }[] = [];
  
  constructor(store: StateFlow<T>) {
    this.store = store;
    this.init();
  }
  
  private init() {
    // 拦截setState并记录变化
    const originalSetState = this.store.setState;
    this.store.setState = (partial) => {
      const stateBefore = this.store.getState();
      originalSetState(partial);
      const stateAfter = this.store.getState();
      
      const actionType = typeof partial === 'function' 
        ? 'FUNCTION_ACTION' 
        : 'UPDATE';
      
      const entry = {
        type: actionType,
        payload: typeof partial === 'function' ? 'Function' : partial,
        timestamp: Date.now(),
        stateBefore,
        stateAfter
      };
      
      this.actionLog.push(entry);
      
      // 发送到开发者工具
      if (this.connected && typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__) {
        window.__REDUX_DEVTOOLS_EXTENSION__.send(
          { type: actionType },
          stateAfter
        );
      }
    };
    
    // 连接到Redux DevTools
    if (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__) {
      const devTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({
        name: 'StateFlow Store'
      });
      
      devTools.init(this.store.getState());
      
      devTools.subscribe((message) => {
        if (message.type === 'DISPATCH' && message.payload.type === 'JUMP_TO_ACTION') {
          const index = parseInt(message.payload.actionId, 10);
          if (this.actionLog[index]) {
            originalSetState(() => this.actionLog[index].stateAfter);
          }
        }
      });
      
      this.connected = true;
    }
  }
  
  // 公开API
  getActionLog() {
    return [...this.actionLog];
  }
  
  jumpToAction(index: number) {
    if (this.actionLog[index]) {
      this.store.setState(() => this.actionLog[index].stateAfter);
    }
  }
}

// 扩展window类型
declare global {
  interface Window {
    __REDUX_DEVTOOLS_EXTENSION__?: any;
  }
}

// 创建DevTools
const connectDevTools = <T>(store: StateFlow<T>) => {
  const devTools = new StateFlowDevTools(store);
  return {
    ...store,
    devTools
  };
};

总结

我们从零设计并实现了StateFlow,一个功能全面且高性能的状态管理库。它具有:

  1. 核心API简洁易用:仅提供getState、setState、subscribe和select四个核心方法
  2. 高效的状态更新机制:使用不可变更新和浅比较优化性能
  3. 灵活的中间件系统:支持日志、异步操作、性能监控等扩展功能
  4. 精确的选择器系统:支持组合选择器和记忆化,避免不必要的重渲染
  5. 内置的时间旅行功能:方便调试和理解状态变化过程
  6. 可选的持久化方案:支持本地存储、会话存储或自定义存储引擎
  7. 与React Concurrent Mode协作:利用React 18的新特性优化用户体验
  8. 完善的调试工具:可视化状态变化,支持时间旅行调试

通过这次"造轮子"实践,我们不仅深入理解了状态管理的核心概念和不同设计模式的优劣,也学习了如何平衡API简洁性和功能丰富性。这个项目虽然是个"玩具级"实现,但包含了现代状态管理库的大部分核心理念和技术,希望对你理解前端状态管理有所帮助!