基于 React Hook 封装 Store 的三种方案

基于 React Hook 封装 Store 的三种方案

方案一:基于 useSyncExternalStore 的轻量级 Store(推荐)
import { useSyncExternalStore } from 'react';

type Store<T> = {
  state: T;
  listeners: Set<() => void>;
};

function createStore<T>(initialState: T) {
  const store: Store<T> = {
    state: initialState,
    listeners: new Set(),
  };

  const setState = (updater: (prev: T) => T) => {
    store.state = updater(store.state);
    store.listeners.forEach(listener => listener());
  };

  const subscribe = (listener: () => void) => {
    store.listeners.add(listener);
    return () => store.listeners.delete(listener);
  };

  const useStore = <S>(selector: (state: T) => S): S => {
    return useSyncExternalStore(
      subscribe,
      () => selector(store.state),
      () => selector(initialState)
    );
  };

  return [useStore, setState] as const;
}

特性:零依赖、无 Provider、精准渲染

方案二:基于 Context + useReducer
import { createContext, useContext, useReducer } from 'react';

type State = { count: number };
type Action = { type: 'INCREMENT' } | { type: 'DECREMENT' };

const StoreContext = createContext<{
  state: State;
  dispatch: React.Dispatch<Action>;
}>(null!);

function StoreProvider({ children }) {
  const [state, dispatch] = useReducer(
    (prev: State, action: Action) => {
      switch (action.type) {
        case 'INCREMENT': return { ...prev, count: prev.count + 1 };
        case 'DECREMENT': return { ...prev, count: prev.count - 1 };
        default: return prev;
      }
    },
    { count: 0 }
  );

  return (
    <StoreContext.Provider value={{ state, dispatch }}>
      {children}
    </StoreContext.Provider>
  );
}

function useStore() {
  const { state, dispatch } = useContext(StoreContext);
  return {
    count: state.count,
    increment: () => dispatch({ type: 'INCREMENT' }),
    decrement: () => dispatch({ type: 'DECREMENT' })
  };
}

优势:支持中间件、复杂状态管理

方案三:基于闭包的轻量实现
import { useState, useMemo } from 'react';

function createStore<T>(initialState: T) {
  let state = initialState;
  const listeners = new Set<() => void>();

  const setState = (updater: (prev: T) => T) => {
    state = updater(state);
    listeners.forEach(listener => listener());
  };

  function useStore(): [T, typeof setState] {
    const [, forceUpdate] = useState({});
    
    useMemo(() => {
      listeners.add(forceUpdate);
      return () => { listeners.delete(forceUpdate); };
    }, []);

    return [state, setState];
  }

  return useStore;
}

特点:<20行代码实现

方案选型对比
方案适用场景优点缺点
useSyncExternalStore大型应用全局状态高性能、无 Provider 污染需要 React 18+
Context + Reducer复杂业务流支持中间件、类型安全需要 Provider 包裹
闭包实现小型应用/组件间共享实现简单、零依赖无法跨组件树隔离状态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值