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
相关产品推荐
相关产品推荐

