React自定义useFetch Hook因setSearchTerm触发无限循环求助
React自定义useFetch Hook触发无限循环问题解决
问题根源
你在AppProvider组件的顶层直接调用了setSearchTerm('s'),这会导致组件每次渲染时都执行状态更新:状态更新触发组件重新渲染,重新渲染时又会再次执行setSearchTerm,如此往复形成无限循环。useFetch的url变化触发请求只是循环过程中的附带现象,核心问题是未受控的状态更新调用。
解决方案
把setSearchTerm的调用放到useEffect中,通过依赖数组控制执行时机,确保只在组件挂载或特定条件下执行一次。
修改后的AppProvider代码
import React, { useContext, useState, useEffect } from "react"; import { useFetch } from "../hooks/useFetch"; const context = React.createContext(); const AppProvider = ({ children }) => { const url = "https://www.thecocktaildb.com/api/json/v1/1/search.php?s="; const [searchTerm, setSearchTerm] = useState("a"); // 仅在组件挂载时执行一次状态更新 useEffect(() => { setSearchTerm('s'); }, []); useFetch(`${url}${searchTerm}`); return ( <context.Provider value={"hello"}> {children} </context.Provider> ) } const useGlobal = () => { return useContext(context); } export { AppProvider, useGlobal };
可选优化:useFetch Hook的稳定性提升
虽然不是当前循环的直接原因,但可以用useCallback包裹getData函数,避免每次组件渲染时创建新的函数实例,优化useEffect的触发逻辑:
import { useEffect, useState, useCallback } from "react"; export const useFetch = (url) => { const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const getData = useCallback(async () => { try { setLoading(true); const response = await fetch(url); const jsonResponse = await response.json(); setData(jsonResponse); } catch (err) { console.log(err); } finally { setLoading(false); } }, [url]); useEffect(() => { getData(); }, [getData]) return { data, loading }; }
内容的提问来源于stack exchange,提问作者mahziar_mohammadrezei
相关产品推荐
相关产品推荐

