基于Window的React Hook导致Next.js侧边栏闪烁的解决方法
解决Next.js侧边栏导航闪烁问题
问题根源
你的Hook在组件挂载时,初始sidebarWidth固定设为SIDEBAR_WIDTH,而正确的宽度计算逻辑要等到useEffect执行后才触发。Next.js页面导航时组件会重新挂载,这就导致页面先渲染窄侧边栏,紧接着useEffect执行后切换到展开宽度,从而出现闪烁。
解决方案
直接在useState初始化时就根据当前窗口宽度设置正确的初始值,避免后续调整导致的闪烁。同时要兼容服务器端渲染(SSR)场景,因为服务器环境没有window对象。
修改后的完整代码
export const useSidebarWidth = () => { // 初始化时直接计算正确宽度,兼容SSR const initialSidebarWidth = typeof window !== 'undefined' ? window.innerWidth < SIDEBAR_BREAKPOINT ? SIDEBAR_WIDTH : SIDEBAR_WIDTH_EXPANDED : SIDEBAR_WIDTH; // 服务器端 fallback 值 const [sidebarWidth, setSidebarWidth] = useState(initialSidebarWidth); const handleResize = () => { if (window.innerWidth < SIDEBAR_BREAKPOINT) { setSidebarWidth(SIDEBAR_WIDTH); } else { setSidebarWidth(SIDEBAR_WIDTH_EXPANDED); } }; useEffect(() => { window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); const isExpanded = sidebarWidth === SIDEBAR_WIDTH_EXPANDED; return { sidebarWidth, isExpanded, }; };
优化说明
- 初始值计算:客户端初始化时直接根据窗口宽度判断,组件挂载就渲染正确的侧边栏宽度,避免后续状态变更导致的闪烁。
- SSR兼容:通过
typeof window !== 'undefined'判断环境,服务器端返回默认的窄宽度,避免SSR报错。 - 简化逻辑:移除了不必要的
useMemo,直接通过sidebarWidth判断展开状态,逻辑更简洁。
内容的提问来源于stack exchange,提问作者Pierre Olivier Tran
相关产品推荐
相关产品推荐

