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

React自定义useAPI Hook中useEffect无限循环问题排查与解决

问题分析与解决方案

问题根源

  1. 无限循环的核心逻辑错误:你把data设为useEffect的依赖,但getDogCollection中会调用setData(result)更新data——data更新触发useEffect重新执行,再次发起请求并更新data,形成无限闭环。
  2. useCallback依赖缺失:getDogCollection里用到了url和options,但useCallback的依赖数组是空的,这会导致函数始终捕获初始的url/options,如果这两个参数变化,请求不会使用新值;另外你在console.log中使用了data,但没把它加入依赖,这里拿到的是闭包中的旧data,属于隐性bug。
  3. 需求逻辑偏差:你想让请求在data变化时执行,但API请求的触发条件应该是请求参数变化(如url/options)或手动触发,而非请求结果data变化。

修复方案

基础版:参数变化时自动请求

调整依赖项,让请求仅在url或options变化时触发,同时补全useCallback的依赖:

import { useCallback, useEffect, useState } from "react";

export const useAPI = (url, options) => {
    const [data, setData] = useState([]);

    const getDogCollection = useCallback(() => {
        fetch(url, options)
            .then((res) => {
                if (!res.ok) throw new Error('请求失败'); // 处理HTTP错误
                return res.json();
            })
            .then((result) => {
                setData(result);
            })
            .catch(err => console.error('请求出错:', err)); // 不要忽略错误
    }, [url, options]); // 补全依赖,确保参数变化时函数更新

    useEffect(() => {
        getDogCollection();
    }, [getDogCollection]); // 依赖更新后的getDogCollection,触发请求

    return data;
};

进阶版:支持手动触发

如果需要手动触发请求(比如点击按钮刷新),可以新增一个trigger参数:

import { useCallback, useEffect, useState } from "react";

export const useAPI = (url, options, trigger = 0) => {
    const [data, setData] = useState([]);

    const getDogCollection = useCallback(() => {
        fetch(url, options)
            .then((res) => {
                if (!res.ok) throw new Error('请求失败');
                return res.json();
            })
            .then((result) => {
                setData(result);
            })
            .catch(err => console.error('请求出错:', err));
    }, [url, options, trigger]); // 加入trigger,值变化时触发请求

    useEffect(() => {
        getDogCollection();
    }, [getDogCollection]);

    return data;
};

// 使用示例:
// const [refreshTrigger, setRefreshTrigger] = useState(0);
// const data = useAPI('/api/dogs', {}, refreshTrigger);
// 点击按钮时调用 setRefreshTrigger(prev => prev + 1) 触发刷新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:20:33