React+Redux天气应用中useEffect未触发fetch请求问题求助
问题排查与解决方法
按优先级逐一排查修复即可解决问题:
1. 解决useEffect不执行的问题
你代码中useEffect内部的console.log('calling fetch')未打印,说明副作用根本没有触发,先排查两点:
- 确认
App组件中正确引入并渲染了GetWeather组件,没有多余的条件渲染逻辑导致组件挂载后立刻被卸载 - 移除
<main>标签上的无效if属性,React原生不支持if属性,改为标准条件渲染写法:
return ( <> {weather.weather && ( <main> <Weather weather={ weather }/> </main> )} <button onClick={ fetchWeather }>Go!</button> </> )
不要把按钮放在条件渲染内部,避免初始状态下按钮不存在,无法手动触发请求。
2. 修复请求逻辑,避免静默失败
Insomnia能请求成功是因为桌面端工具没有跨域限制,浏览器端需要添加错误捕获逻辑,直接定位请求失败原因:
const fetchWeather = useCallback(async () => { console.log('fetching'); try { const response = await fetch('https://api.openweathermap.org/data/2.5/weather?q=stockholm&appid=1dc27327c1655e53a85e6e5a889fccee'); // fetch默认只会在网络错误时抛出异常,需要手动判断HTTP状态码 if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } const data = await response.json(); dispatch(setWeather(data)); } catch (err) { console.error('获取天气数据出错:', err); } }, [dispatch])
添加捕获逻辑后可直接在控制台看到具体报错,是跨域、appid无效还是请求限额超限一目了然。
3. 调整useEffect依赖逻辑
useCallback包裹的fetchWeather依赖的dispatch是React Redux提供的稳定引用,永远不会变更,所以useEffect依赖fetchWeather只会在页面加载时执行一次,符合你的需求:
useEffect(() => { console.log('calling fetch'); fetchWeather(); }, [fetchWeather]);
如果你不想依赖fetchWeather,也可以直接把依赖设为空数组,加一行注释关闭eslint的依赖检查即可,效果完全一致。
可选优化:支持搜索城市
如果后续要接入搜索表单,只需要给fetchWeather加一个城市参数即可:
const fetchWeather = useCallback(async (city = 'stockholm') => { // 拼接请求参数的时候用encodeURIComponent处理城市名,避免中文/特殊字符报错 const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&appid=1dc27327c1655e53a85e6e5a889fccee`); // 剩余逻辑保持不变 }, [dispatch]) // 搜索表单提交的时候调用 const handleSearch = (e) => { e.preventDefault(); fetchWeather(searchInputValue); }
内容的提问来源于stack exchange,提问作者crashdelta
相关产品推荐
相关产品推荐

