React自定义Hook陷入无限循环问题求助
解决React自定义Hook中因Query参数导致的无限循环问题
问题根源
- Query对象引用不稳定:Home组件函数体内直接创建的
query对象,每次组件渲染都会生成新的实例,导致传给useGetWeather的query依赖频繁变化,触发Hook内的useEffect重复执行。 - 直接修改传入的Query对象:在Hook的第二个useEffect中,
let localQuery = query是引用赋值,后续修改localQuery的经纬度会直接污染Home组件中的原query对象,进一步触发组件重新渲染,形成循环。
修复步骤
1. 缓存Home组件中的Query对象
用useMemo包裹query,仅在经纬度变化时重新生成对象,保证引用稳定:
// Home.js 修改部分 import { useState, useMemo } from "react"; // ... 其他代码 const query = useMemo(() => ({ current_weather: true, hourly: "temperature_2m,weathercode,is_day", forecast_days: 1, latitude: latitude, longitude: longitude, }), [latitude, longitude]);
2. 在Hook中避免修改原Query对象
创建新的查询对象组合参数,不直接修改传入的query:
// useGetWeather.js 第二个useEffect修改部分 useEffect(() => { const abortCont = new AbortController(); // 新建对象,避免修改原query const localQuery = { ...query, latitude: pos.latitude, longitude: pos.longitude, }; if (typeof pos.longitude !== "undefined") { fetch( "https://api.open-meteo.com/v1/forecast?" + new URLSearchParams(localQuery).toString(), { signal: abortCont.signal } ) // ... 后续fetch逻辑保持不变 } return () => abortCont.abort(); }, [pos, query]);
3. 可选:优化Hook依赖项
如果query中的固定字段(如current_weather)不会变化,可以只依赖这些字段,进一步减少不必要的触发:
// useGetWeather.js 第二个useEffect依赖修改为 }, [pos, query.current_weather, query.hourly, query.forecast_days]);
额外优化建议
Home组件中用index作为列表项的key更稳定,避免countId导致的key不稳定问题:
// Home.js 渲染小时预报部分修改 {weatherData && weatherData.hourly.temperature_2m.flatMap((temp, index) => { let d = new Date(weatherData.hourly.time[index]); let currDate = new Date(); currDate.setMinutes(0); currDate.setSeconds(0); if (d.getHours() < currDate.getHours()) { return []; } return ( <div className="tempItem" key={index}> // ... 其他内容保持不变 </div> ); })}
内容的提问来源于stack exchange,提问作者Diogo Martins
相关产品推荐
相关产品推荐

