我正在学习 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,但由于钩子不能位于函数内部,我不知道如何使其工作。
任何帮助表示赞赏
您的代码存在多处错误(当然不完全错误,但它不是“反应式”方法)。
为了修复你的组件,你需要了解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>
);
}