React天气应用删除城市后组件不重新渲染问题求助
解决React天气应用删除城市后首页不刷新的问题
你的核心问题在于全局变量无法触发React组件的重新渲染,且组件外部的初始化代码仅执行一次,导致删除城市后本地存储数据更新,但首页组件不会重新获取最新数据。
具体问题点
savedCities是全局变量,React不会追踪全局变量的变化,即便本地存储的数据变了,组件也不会重新渲染。- 组件外部的
await getCities()仅在组件首次加载前执行一次,之后删除城市跳转回首页时,不会重新执行该逻辑获取最新的本地存储数据。 savedCities.map(async (city, index) => { ... })存在异步问题:map返回的是Promise数组,不会等待所有请求完成就继续执行,导致组件可能在天气数据还没获取完就渲染了。
解决方案
将全局变量改为组件内部的状态,并用useEffect在组件挂载(或数据变化时)重新获取并更新数据:
修改后的CityList.jsx代码:
import { useState, useEffect } from 'react'; import { CityListCard } from "./CityListCard"; export function CityList() { const [savedCities, setSavedCities] = useState([]); useEffect(() => { const fetchSavedCities = async () => { // 从本地存储获取保存的城市 const storedCities = localStorage.getItem('savedCities'); if (!storedCities) { setSavedCities([]); return; } let cities = JSON.parse(storedCities); const OWMAppId = 'xxxxxxxxxxxxxxxxxxxxx'; const units = 'metric'; const langapi = 'en'; // 用Promise.all等待所有天气请求完成,避免异步竞态问题 const citiesWithWeather = await Promise.all( cities.map(async (city) => { try { const response = await fetch( `https://api.openweathermap.org/data/3.0/onecall?lat=${city.coords.lat}&lon=${city.coords.lng}&exclude=part&appid=${OWMAppId}&units=${units}&lang=${langapi}`, { headers: { 'Accept': 'application/json; charset=UTF-8' } } ); const weatherData = await response.json(); return { ...city, weather: weatherData }; } catch (error) { console.error(`获取${city.name}天气失败:`, error); return city; // 请求失败时返回原城市数据,避免渲染出错 } }) ); setSavedCities(citiesWithWeather); }; fetchSavedCities(); }, []); // 空依赖数组:组件挂载时执行一次;若需监听本地存储变化,可添加storage事件监听 return ( <div className="flex flex-col gap-4"> {savedCities.length > 0 ? ( savedCities.map(city => ( <CityListCard key={city.id} city={city} /> )) ) : ( <p>暂无保存的城市</p> )} </div> ); }
关键改进点
- 用useState管理状态:
savedCities变为组件内部状态,调用setSavedCities时会触发组件重新渲染,确保展示最新数据。 - 用useEffect执行异步逻辑:将获取城市和天气的逻辑放在
useEffect中,组件挂载时自动执行,跳转回首页时组件重新挂载,会再次执行该逻辑获取最新的本地存储数据。 - 用Promise.all处理批量异步请求:确保所有天气数据请求完成后再更新状态,避免数据不完整就渲染的问题。
- 添加错误捕获:处理天气请求失败的情况,防止组件崩溃。
额外优化建议
如果你的应用中存在多个页面修改本地存储的情况,可以在useEffect中添加storage事件监听,实时响应其他标签页或页面修改本地存储的操作:
useEffect(() => { // ... 原有fetchSavedCities逻辑 const handleStorageChange = () => { fetchSavedCities(); }; window.addEventListener('storage', handleStorageChange); return () => { window.removeEventListener('storage', handleStorageChange); }; }, []);
内容的提问来源于stack exchange,提问作者feub
相关产品推荐
相关产品推荐

