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

useEffect条件渲染异常:isMobile为true时仍触发Fetch请求

解决React useEffect在isMobile为true时仍触发数据请求的问题

可能的问题根源

  1. 初始isMobile状态不准确:如果useWindowSize钩子的初始状态是硬编码的默认值(比如false),而非直接计算当前窗口宽度,会导致组件初始渲染时isMobile为false,触发请求后才更新为true,最终出现请求已发送的情况。
  2. 闭包导致的状态捕获问题:若getData函数定义在useEffect外部,可能捕获到旧的isMobile值,导致内部的判断逻辑失效。

具体解决方案

1. 修正useWindowSize的初始状态

确保useWindowSize在组件挂载时就直接计算当前窗口宽度,而非依赖resize事件更新:

function useWindowSize() {
  const [isMobile, setIsMobile] = useState(() => {
    // 初始渲染时直接计算窗口尺寸,兼容服务端渲染场景
    return typeof window !== 'undefined' ? window.innerWidth < 992 : false;
  });

  useEffect(() => {
    const handleResize = () => {
      setIsMobile(window.innerWidth < 992);
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return isMobile;
}

2. 在useEffect内直接前置判断逻辑

把isMobile的判断放在useEffect最开头,直接终止执行,避免进入请求逻辑:

useEffect(() => {
  // 不符合条件立即返回,跳过请求逻辑
  if (isMobile) return;

  const fetchData = async () => {
    const data = await fetchClientApi();
    setState(data);
  };

  fetchData();
}, [isMobile]);

3. 添加请求取消机制(可选)

如果担心初始状态仍有延迟导致请求发出,可以用AbortController取消未完成的请求,避免无效数据更新:

useEffect(() => {
  const controller = new AbortController();
  const signal = controller.signal;

  if (isMobile) {
    controller.abort();
    return;
  }

  const fetchData = async () => {
    try {
      // 将signal传入请求方法,支持请求取消
      const data = await fetchClientApi({ signal });
      setState(data);
    } catch (error) {
      // 忽略取消请求的错误,只处理其他异常
      if (error.name !== 'AbortError') {
        console.error('请求失败:', error);
      }
    }
  };

  fetchData();

  // 组件卸载或依赖更新时自动取消请求
  return () => controller.abort();
}, [isMobile]);

内容的提问来源于stack exchange,提问作者Vladimir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 08:46:16