Next.js小屏幕条件渲染延迟问题及优化方案咨询
这种延迟情况不正常,完全可以通过优化消除
原代码的核心问题是:初始状态windowWidth为undefined,第一次渲染时直接返回false;而useEffect是在组件首次渲染完成后才执行的——这就导致真实的屏幕尺寸判断要等到一轮渲染结束后才会更新,进而出现元素延迟显示的问题。
两种优化方案,按需选择:
方案1:直接初始化状态为当前屏幕宽度
跳过useEffect的等待,组件初始化时直接读取window.innerWidth,消除首次渲染的延迟,同时给resize事件加节流避免频繁重渲染:
const useMobile = () => { // 初始化时直接获取当前窗口宽度,避免初始状态为undefined const [windowWidth, setWindowWidth] = useState<number>(window.innerWidth); useEffect(() => { const handleResize = () => { setWindowWidth(window.innerWidth); }; // 自定义节流函数,减少resize事件触发频率 const throttle = (func: Function, delay: number) => { let timer: NodeJS.Timeout | null = null; return (...args: any[]) => { if (!timer) { timer = setTimeout(() => { func.apply(this, args); timer = null; }, delay); } }; }; const throttledHandleResize = throttle(handleResize, 100); window.addEventListener("resize", throttledHandleResize); return () => window.removeEventListener("resize", throttledHandleResize); }, []); return windowWidth <= 860; };
方案2:使用原生matchMediaAPI(更推荐)
浏览器原生的媒体查询API可以直接监听屏幕尺寸阈值变化,不需要自己处理resize事件和尺寸判断,性能更优:
const useMobile = () => { // 匹配最大宽度860px的媒体查询,初始直接获取匹配结果 const mediaQuery = window.matchMedia("(max-width: 860px)"); const [isSmallScreen, setIsSmallScreen] = useState<boolean>(mediaQuery.matches); useEffect(() => { const handleMediaChange = (e: MediaQueryListEvent) => { setIsSmallScreen(e.matches); }; mediaQuery.addEventListener("change", handleMediaChange); return () => mediaQuery.removeEventListener("change", handleMediaChange); }, []); return isSmallScreen; };
这个方案的优势:
- 初始状态直接获取当前媒体查询的匹配结果,无任何延迟
- 只有当屏幕尺寸跨越860px阈值时才会触发状态更新,不会像resize事件那样频繁触发重渲染
SSR场景兼容处理
如果你的应用是服务端渲染(SSR),需要处理window不存在的情况,只需在初始化时加个判断:
// 方案1的SSR兼容写法 const initialWidth = typeof window !== 'undefined' ? window.innerWidth : 0; const [windowWidth, setWindowWidth] = useState<number>(initialWidth); // 方案2的SSR兼容写法 const initialMatch = typeof window !== 'undefined' ? window.matchMedia("(max-width: 860px)").matches : false; const [isSmallScreen, setIsSmallScreen] = useState<boolean>(initialMatch);
内容的提问来源于stack exchange,提问作者ledmatrix
相关产品推荐
相关产品推荐

