React中纯 localStorage 与 Context + useReducer + localStorage对比

发布于:2025-09-02 ⋅ 阅读:(31) ⋅ 点赞:(0)

在 React 中,直接使用 纯 localStorageContext + useReducer + localStorage 的状态管理方案有显著区别,主要体现在 状态同步能力代码架构维护性 等方面。以下是详细对比:


1. 纯 localStorage 方案

实现方式

直接在组件中读写 localStorage,无全局状态管理:

function ThemeSwitcher() {
  const [theme, setTheme] = useState(
    () => localStorage.getItem('theme') || 'light'
  );

  const handleChange = (newTheme) => {
    setTheme(newTheme);
    localStorage.setItem('theme', newTheme);
  };

  return (
    <select value={theme} onChange={(e) => handleChange(e.target.value)}>
      <option value="light">Light</option>
      <option value="dark">Dark</option>
    </select>
  );
}
特点
优点 缺点
1. 实现简单,无需额外库 1. 状态不同步:多个组件无法实时共享同一份数据
2. 适合极简场景 2. 重复代码:每个组件需单独处理存储逻辑
3. 无性能开销(仅读写存储) 3. 难以维护:业务复杂时逻辑分散

2. Context + useReducer + localStorage 方案

实现方式

将状态提升到全局,通过 Context 共享,并自动同步到 localStorage

// 1. 定义状态和 reducer
const initialState = { theme: 'light' };
function reducer(state, action) {
  switch (action.type) {
    case 'SET_THEME':
      return { ...state, theme: action.payload };
    default:
      return state;
  }
}

// 2. 创建 Context 和 Provider
const AppContext = createContext();

function AppProvider({ children }) {
  const [state, dispatch] = useReducer(
    reducer,
    JSON.parse(localStorage.getItem('appState')) || initialState
  );

  // 自动同步到 localStorage
  useEffect(() => {
    localStorage.setItem('appState', JSON.stringify(state));
  }, [state]);

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

// 3. 在组件中使用
function ThemeSwitcher() {
  const { state, dispatch } = useContext(AppContext);
  return (
    <select
      value={state.theme}
      onChange={(e) => dispatch({ type: 'SET_THEME', payload: e.target.value })}
    >
      <option value="light">Light</option>
      <option value="dark">Dark</option>
    </select>
  );
}
特点
优点 缺点
1. 状态全局共享:所有组件实时响应变化 1. 代码量稍多(需设置 Context/Reducer)
2. 逻辑集中:易于维护和扩展 2. 小型项目可能过度设计
3. 自动持久化:状态变更自动同步到存储 3. 需处理 Provider 嵌套问题

核心区别对比

对比维度 纯 localStorage Context + useReducer + localStorage
状态同步 需手动触发,组件间不同步 自动同步,全局状态一致
代码组织 逻辑分散在各组件 集中管理,高内聚低耦合
维护性 难扩展,易出现重复代码 易于扩展和维护
性能 直接操作存储,无额外开销 有 Context 的渲染开销(可通过 memo 优化)
适用场景 简单页面、独立组件 中大型应用、需共享状态的场景

如何选择?

  1. 纯 localStorage

    • 适合:
      • 简单页面(如个人博客的主题切换)
      • 独立组件(如一个无需共享的表单草稿)
    • 示例:
      // 独立计数器,无需共享状态
      function Counter() {
        const [count, setCount] = useState(Number(localStorage.getItem('count')) || 0);
        useEffect(() => {
          localStorage.setItem('count', String(count));
        }, [count]);
        return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
      }
      
  2. Context + useReducer + localStorage

    • 适合:
      • 多组件共享状态(如用户登录信息、全局主题)
      • 复杂交互(如购物车、表单多步骤流程)
    • 示例:
      // 全局购物车状态
      function Cart() {
        const { state, dispatch } = useContext(AppContext);
        return (
          <div>
            {state.cartItems.map(item => <CartItem key={item.id} item={item} />)}
          </div>
        );
      }
      

更优解:结合 Zustand

如果觉得 Context + useReducer 太重,但需要全局状态管理,推荐使用 Zustand(轻量级状态库,内置持久化):

import create from 'zustand';
import { persist } from 'zustand/middleware';

const useStore = create(persist(
  (set) => ({
    theme: 'light',
    setTheme: (theme) => set({ theme }),
  }),
  {
    name: 'app-storage', // localStorage 的 key
  }
));

// 在组件中使用
function ThemeSwitcher() {
  const theme = useStore(state => state.theme);
  const setTheme = useStore(state => state.setTheme);
  return (
    <select value={theme} onChange={(e) => setTheme(e.target.value)}>
      <option value="light">Light</option>
      <option value="dark">Dark</option>
    </select>
  );
}

总结

  • 直接 localStorage:简单粗暴,适合局部状态。
  • Context + useReducer + localStorage:专业方案,适合全局状态。
  • Zustand 等库:折中选择,简化全局状态管理。

网站公告

今日签到

点亮在社区的每一天
去签到