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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 03:02:19