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

React自定义useFetch Hook引发无限循环的原因排查与解决

解决React自定义Hook调用API的无限循环问题

问题根源分析

你遇到的无限循环是因为useEffect的依赖项设为了data:每次调用fetchData会更新data状态,触发useEffect重新执行,再次调用fetchData,形成闭环。

另外你提到把url作为依赖项时请求没触发,本质是因为自定义Hook里的fetchData每次组件渲染都会重新创建,React会因为依赖项不完整(缺少fetchData)而跳过useEffect执行。

解决方案

1. 优化自定义Hook useFetch.jsx

用useCallback包裹fetchData,保证函数引用的稳定性,避免不必要的重新创建:

import React, { useState, useCallback } from "react";
import apiKey from "../apiKey";

function useFetch() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);

  const fetchData = useCallback(async (
    url,
    options = {
      method: "GET",
      headers: {
        "X-RapidAPI-Key": apiKey,
        "X-RapidAPI-Host": "unogsng.p.rapidapi.com",
      },
    }
  ) => {
    setLoading(true);
    try {
      const response = await fetch(url, options);
      const jsonData = await response.json();
      setData(jsonData);
    } catch (err) {
      setError(err);
    } finally {
      // 确保请求结束后无论成败都关闭加载状态
      setLoading(false);
    }
  }, [apiKey]); // 依赖apiKey,若apiKey是固定值可留空

  return [data, error, loading, fetchData];
}

export default useFetch;

2. 修复Home.jsx的useEffect逻辑

调整依赖项为稳定的fetchData和url,同时处理数据、加载和错误状态:

import React, { useState, useEffect } from "react";
import useFetch from "../hooks/useFetch";

const Home = () => {
  const [newShows, setNewShows] = useState([]);
  const [data, error, loading, fetchData] = useFetch();
  const today = new Date();
  const date = today.toISOString().substring(0, 10);
  const url = `https://unogsng.p.rapidapi.com/search?newdate=${date}&limit=10`;

  useEffect(() => {
    async function getNewShows() {
      await fetchData(url);
      // 根据接口返回结构处理数据,这里假设结果存在results字段
      if (data) {
        setNewShows(data.results || []);
      }
    }
    getNewShows();
  }, [fetchData, url]); // 仅当fetchData或url变化时执行

  // 加载状态展示
  if (loading) return <div>加载中...</div>;
  // 错误状态展示
  if (error) return <div>获取数据失败:{error.message}</div>;

  return (
    <div>
      <h1>今日最新剧集</h1>
      <ul>
        {newShows.map((show, idx) => (
          <li key={idx}>{show.title}</li> {/* 替换为接口实际返回的字段 */}
        ))}
      </ul>
    </div>
  );
};

export default Home;

关键说明

  • 用useCallback稳定fetchData的引用,确保useEffect依赖项正确,避免无意义的重复执行。
  • useEffect依赖url和fetchData,保证组件挂载时执行一次,且每天日期变化时自动重新请求当日数据。
  • 新增finally块处理加载状态,避免请求失败后一直显示加载中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:40:25