React 应用程序中组件无法重新渲染的问题

问题描述 投票:0回答:1

我正在学习 React,目前正在开发一个简单的天气应用程序作为练习的方式。它工作正常,但我已经被一个问题困扰了很长一段时间。

该应用程序有 2 个页面(使用 React-router-dom),一个主页带有用于查找城市的输入表单(使用 api.mapbox.com)。当从结果列表中单击一个城市时,会出现该城市天气的预览(api.openweathermap.org),然后用户可以单击 + 按钮来保存该城市(使用本地存储)。保存的城市在主页上显示为卡片。可以使用天气页面底部的按钮从已保存的城市中删除城市。它只是从本地存储中存储的数组中删除城市,然后重定向到主页。

问题是重定向后我仍然看到“已删除”的城市卡,我必须刷新页面才能看到它被删除。我想我需要在删除城市后使用 useEffect 挂钩重新渲染城市列表,但我无法让它工作。我错过了一些东西,但无法弄清楚是什么。 下面是我的 CityList.jsx 组件,它呈现主页中已保存的城市:

import { CityListCard } from "./CityListCard";

let savedCities

const getCities = async () => {
    if (localStorage.getItem('savedCities')) {
        savedCities = JSON.parse(localStorage.getItem('savedCities'))
        const OWMAppId = 'xxxxxxxxxxxxxxxxxxxxx'
        const units = 'metric'
        const langapi = 'en'

        savedCities.map(async (city, index) => {
            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 data = await response.json()
            savedCities[index].weather = data
        })
    }
}

await getCities()

export function CityList() {
    return <div className="flex flex-col gap-4">
        {savedCities &&
            savedCities.map(city => (
                <CityListCard key={city.id} city={city} />
            ))
        }
    </div>
}

我想我必须添加一个useEffect并依赖于savedCities,但由于钩子不能位于函数内部,我不知道如何使其工作。

任何帮助表示赞赏

javascript reactjs react-hooks
1个回答
0
投票

您的代码存在多处错误(当然不完全错误,但它不是“反应式”方法)。

  • 您正在 React 组件之外声明变量。这使其成为非反应性的,这意味着 React 将不知道其何时更新,因此不会重新渲染组件。
  • 您也在组件外部进行 API 调用,同样,React 组件不知道正在进行此调用,如果您想在进行此调用时显示加载程序怎么办?组件如何知道其状态?
  • 此外,您正在更新函数外部本地创建的变量 异步函数调用内的范围,理想情况下函数不应更新其范围之外的变量,它应该返回某种形式的数据,进而更新变量。

为了修复你的组件,你需要了解React期望你的组件如何编写,主要了解钩子的使用,其中两个主要是

useState
useEffect

更新使用

useState
声明的变量将告诉 React 在检测到该变量发生更改时重新渲染它。

useEffect
主要用于副作用,即渲染后组件中发生的任何操作或行为,并且不会直接影响当前组件的渲染周期。这些副作用可能包括数据获取、订阅、手动更改 DOM 或与外界的其他交互等任务。

您可以在 React 网站上阅读更多相关信息 - https://react.dev/reference/react/hooks

现在修复你的组件,它应该看起来有点像这样,可能不完全工作,但你会得到一个公平的想法

import { CityListCard } from "./CityListCard";
import { useState, useEffect } from "react";



const getCities = async () => {
    if (localStorage.getItem('savedCities')) {
        const savedCities = JSON.parse(localStorage.getItem('savedCities')  || '[]')
        const OWMAppId = 'xxxxxxxxxxxxxxxxxxxxx'
        const units = 'metric'
        const langapi = 'en'

        savedCities.map(async (city, index) => {
            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 data = await response.json()
            savedCities[index].weather = data
        })
    }
}



export function CityList() {
  const [cities, setCities] = useState([]);

  useEffect(() => {
    // make the API call here and set the state
    getCities().then((data) => {
      setCities(data);
    });
  }, []); // dependencies variables are added here to re-run the effect when they change, if 

  return (
    <div className="flex flex-col gap-4">
      {cities &&
        cities.map((city) => <CityListCard key={city.id} city={city} />)}
    </div>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.