You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
    );
}

关键改进点

  1. 用useState管理状态:savedCities变为组件内部状态,调用setSavedCities时会触发组件重新渲染,确保展示最新数据。
  2. 用useEffect执行异步逻辑:将获取城市和天气的逻辑放在useEffect中,组件挂载时自动执行,跳转回首页时组件重新挂载,会再次执行该逻辑获取最新的本地存储数据。
  3. 用Promise.all处理批量异步请求:确保所有天气数据请求完成后再更新状态,避免数据不完整就渲染的问题。
  4. 添加错误捕获:处理天气请求失败的情况,防止组件崩溃。

额外优化建议

如果你的应用中存在多个页面修改本地存储的情况,可以在useEffect中添加storage事件监听,实时响应其他标签页或页面修改本地存储的操作:

useEffect(() => {
    // ... 原有fetchSavedCities逻辑

    const handleStorageChange = () => {
        fetchSavedCities();
    };

    window.addEventListener('storage', handleStorageChange);

    return () => {
        window.removeEventListener('storage', handleStorageChange);
    };
}, []);

内容的提问来源于stack exchange,提问作者feub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 12:50:14