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

React Native中使用useCallback仍出现无限Fetch循环问题求助

React Native useFetch钩子无限循环问题排查与修复

问题现象

加载标签页时发起Fetch请求出现无限循环,日志反复打印~~ fetchData ~~和~~ fetchData - try ~~,请求后续的响应处理代码完全无法执行。

问题根源

无限循环的核心原因是**useCallback的依赖项不稳定**:

  • 你在TabTwoScreen中传入的body是空对象{},每次组件渲染时,空对象都会被重新创建(引用地址发生变化)
  • useCallback会因为body的引用变化,重新生成fetchData函数
  • useEffect的依赖是fetchData,每次fetchData更新就会触发effect执行,调用fetchData;而fetchData内的状态更新(setIsLoading/setApiData)又会触发组件重新渲染,进而再次创建新的空对象body,形成闭环无限循环

修复方案

方案1:稳定body的引用

如果是GET请求,本身不需要body参数,直接不传或传undefined即可,同时给useFetch设置参数默认值:

// 修改useFetch钩子的参数默认值
export const useFetch = (method: string, url: string, body: any = undefined) => {
  // ... 原有逻辑不变
};

// 在TabTwoScreen中调用
export default function TabTwoScreen() {
  const { isLoading, serverError, apiData } = useFetch(
    'GET',
    'https://jsonplaceholder.typicode.com/posts/1'
  );
}

如果确实需要传空对象,用useMemo稳定其引用:

import { useMemo } from 'react';

export default function TabTwoScreen() {
  const emptyBody = useMemo(() => ({}), []);
  const { isLoading, serverError, apiData } = useFetch(
    'GET',
    'https://jsonplaceholder.typicode.com/posts/1',
    emptyBody
  );
}

方案2:简化钩子逻辑,去掉不必要的useCallback

如果不需要对外暴露fetchData函数,直接把请求逻辑放在useEffect内部,避免依赖项管理的麻烦:

import axios from 'axios';
import { useState, useEffect } from 'react';

export const useFetch = (method: string, url: string, body: any) => {
  const [isLoading, setIsLoading] = useState(false);
  const [apiData, setApiData] = useState(null);
  const [serverError, setServerError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      console.log('~~ fetchData ~~');
      try {
        console.log('~~ fetchData - try ~~');
        const res = await axios({
          method: method,
          url: url,
          data: body,
        });
        console.log('~~ fetchData - res ~~');
        console.log(res);
        const data = res?.data;
        console.log('~~ setApiData - useState ~~');
        console.log(`Data: ${data}`);
        setApiData(data);
      } catch (error: any | unknown) {
        setServerError(error);
      } finally {
        setIsLoading(false);
      }
    };

    setIsLoading(true);
    fetchData();
  }, [url, method, body]);

  return { isLoading, apiData, serverError };
};

额外优化建议

  • 给请求加上中止逻辑,防止组件卸载时请求未完成导致内存泄漏:
    useEffect(() => {
      const abortController = new AbortController();
      const fetchData = async () => {
        try {
          const res = await axios({
            method: method,
            url: url,
            data: body,
            signal: abortController.signal, // 关联中止信号
          });
          // ... 数据处理逻辑
        } catch (error) {
          if (axios.isCancel(error)) return; // 忽略取消请求的错误
          setServerError(error);
        } finally {
          setIsLoading(false);
        }
      };
    
      setIsLoading(true);
      fetchData();
    
      return () => abortController.abort(); // 组件卸载时中止请求
    }, [url, method, body]);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 15:22:34