Zustand+ResizeObserver Hook故障求助:响应式布局未按预期切换
问题排查与修复方案
1. 核心逻辑错误:ResizeObserver分支判断完全写反
你的ResizeObserver回调里,else分支错误地将isDesktop设为true,导致无论窗口宽度是否小于1280,isDesktop永远为true,
修复后的判断逻辑:
const resizeObserver = new ResizeObserver(entries => { for (const entry of entries) { const { clientWidth } = entry.target; if (clientWidth > 1280) { isPhone = false; isDesktop = true; } else { isDesktop = false; // 这里改为false isPhone = true; } set({ isDesktop, isPhone }); } });
2. 组件取值错误:未正确解构Zustand Store属性
useDeviceType返回的是包含isDesktop和isPhone的对象,但你在组件里直接把整个对象赋值给isDesktop变量——对象属于真值,导致{isDesktop ? ...}的判断永远成立。
修复后的组件取值:
const EditEmail = () => { // 解构取出isDesktop布尔值 const { isDesktop } = useDeviceType(); return ( <> {isDesktop ? <ProfileLayout> <Form /> </ProfileLayout> : <Form /> } </> ); };
3. 可选优化:初始状态与内存泄漏处理
- 初始状态不准确:当前Hook默认
isDesktop=false,但页面加载时可能窗口宽度已经大于1280,建议初始化时直接判断一次设备类型:export const useDeviceType = create(set => { let isDesktop = false; let isPhone = false; // 初始化时立即判断一次 const checkDevice = () => { if (typeof document !== 'undefined') { const width = document.body.clientWidth; isDesktop = width > 1280; isPhone = !isDesktop; set({ isDesktop, isPhone }); } }; checkDevice(); // ... 原有ResizeObserver逻辑 ... // 暴露销毁方法,避免内存泄漏 return { isDesktop, isPhone, destroy: () => resizeObserver.disconnect() }; }); - 清理ResizeObserver:在组件卸载时停止观察,避免内存泄漏:
import { useEffect } from 'react'; const EditEmail = () => { const { isDesktop, destroy } = useDeviceType(); useEffect(() => { return () => destroy(); }, [destroy]); // ... 原有渲染逻辑 ... };
内容的提问来源于stack exchange,提问作者Julia Schafer
相关产品推荐
相关产品推荐

