You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将React布局Context替换为Zustand状态仓库 #1590

将React布局Context替换为Zustand状态仓库 #1590

嘿,我正好之前做过类似的迁移,Zustand的简洁性真的能省不少事!下面我一步步给你讲怎么把原来的Context换成Zustand,包括你关心的useWindowSize和初始布局逻辑的放置位置。

首先,先确保你已经安装了Zustand:

npm install zustand
# 或者用yarn
yarn add zustand

接下来,我们创建一个单独的布局store文件(比如src/store/layoutStore.ts),把原来Context里的所有状态、逻辑都迁移过去:

import { create } from 'zustand';
import { useWindowSize } from '../hooks/useWindowSize'; // 替换成你实际的hook路径

// 先定义好你的断点常量(和原来保持一致)
const Breakpoint = {
  MEDIUM: 768,
  LARGE: 1024,
  EXTRA_LARGE: 1280,
};

export const useLayoutStore = create((set) => {
  // 1. 在这里使用useWindowSize,实时获取窗口尺寸
  const windowSize = useWindowSize();

  // 2. 根据窗口宽度计算各断点状态
  const isMobile = windowSize.width <= Breakpoint.MEDIUM;
  const isTablet = windowSize.width > Breakpoint.MEDIUM && windowSize.width < Breakpoint.LARGE;
  const isLaptop = windowSize.width >= Breakpoint.LARGE && windowSize.width < Breakpoint.EXTRA_LARGE;
  const isDesktop = windowSize.width >= Breakpoint.EXTRA_LARGE;

  // 3. 初始布局逻辑:用useEffect执行一次初始化
  useEffect(() => {
    const initialWidth = window.innerWidth;
    const isMobileDevice = initialWidth <= Breakpoint.MEDIUM;
    const isDesktopDevice = initialWidth >= Breakpoint.EXTRA_LARGE;

    if (isMobileDevice) {
      set({ showMobileNavigation: true });
    }
    if (isDesktopDevice) {
      set({ menuIsOpen: true });
    }
  }, []);

  // 4. 定义状态和更新函数
  return {
    // 核心状态
    menuIsOpen: false,
    overlayIsOpen: false,
    showMobileNavigation: false,
    // 断点状态(由windowSize实时计算)
    isMobile,
    isTablet,
    isLaptop,
    isDesktop,

    // 更新函数
    setMenuIsOpen: (isOpen: boolean) => set({ menuIsOpen: isOpen }),
    setOverlayIsOpen: (isOpen: boolean) => set({ overlayIsOpen: isOpen }),
    setShowMobileNavigation: (show: boolean) => set({ showMobileNavigation: show }),
  };
});

关键部分解释:

  • useWindowSize的位置:直接放在store的创建函数里就好!因为Zustand允许在store内部使用React hooks,当窗口大小变化时,useWindowSize会触发store更新,对应的isMobile、isTablet等状态也会自动同步。
  • 初始布局的useEffect:同样放在store内部,空依赖数组保证只在应用初始化时执行一次,完美替代原来Context里的初始逻辑。
  • 无需Provider:Zustand不需要像Context那样用Provider包裹整个应用,你可以在任何组件里直接调用useLayoutStore获取状态或更新函数。

在组件中使用的示例:

比如在导航组件里:

import { useLayoutStore } from '../store/layoutStore';

const Navigation = () => {
  // 只订阅需要的状态,提升性能
  const isMobile = useLayoutStore(state => state.isMobile);
  const menuIsOpen = useLayoutStore(state => state.menuIsOpen);
  const setMenuIsOpen = useLayoutStore(state => state.setMenuIsOpen);

  return (
    <nav>
      {isMobile ? (
        <button onClick={() => setMenuIsOpen(!menuIsOpen)}>
          {menuIsOpen ? '关闭菜单' : '打开菜单'}
        </button>
      ) : (
        <div className="desktop-menu">...</div>
      )}
    </nav>
  );
};

最后,你可以完全移除原来的LayoutContext和LayoutProvider了,Zustand已经帮你搞定全局状态管理!

备注:内容来源于stack exchange,提问作者Cytronic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 15:27:29