React useEffect 未按预期运行
React useEffect not behaving as expected
我正在使用 OpenWeatherAPI,我的获取工作正常。我能够使用 State 将成功获取的数据放入状态。控制台日志出现,我可以看到在网络选项卡中发出的请求。
但是发生了一些有趣的事情,我的 .map()ed 数据并没有像我预期的那样每次都呈现。我将编写代码,按保存,它会显示在屏幕上。但是,如果我刷新页面或重新启动服务器,它就不会出现。有时会在刷新几次后出现。
我很可能在挂钩系统上做错了什么。请指出我做错了什么。
我不能在 promise 解决后直接使用我放入 state 的列表,我需要过滤掉我刚刚在 state 中设置的响应,只得到我需要的 keys/vals 因此你为什么查看 filteredForecasts
的第二个状态。为什么它只是偶尔定期工作?我觉得我有所有正确的 null 检查 if 语句,但它仍然没有按预期工作...
import React from "react";
import WeatherCard from '../WeatherCard';
import "./WeatherList.scss";
const WeatherList = (props) => {
return (
<div className="weather-list-container">
<WeatherCard />
</div>
);
};
export default WeatherList;
import React, { useState, useEffect } from "react";
import "./WeatherCard.scss";
import { getForecast } from "../../api/GET/getForecast";
const WeatherCard = () => {
const [forecasts, setForecasts] = useState([]);
const [filteredForecasts, setFilteredForecasts] = useState([]);
useEffect(() => {
getForecast()
.then((res) => {
const { list } = res;
setForecasts(list);
})
.catch((err) => {
console.log(err);
});
}, []);
useEffect(() => {
if (forecasts.length) {
const uniqueForecasts = Array.from(
new Set(allRelevantData.map((a) => a.day))
).map((day) => {
return allRelevantData.find((a) => a.day === day);
});
setFilteredForecasts(uniqueForecasts);
}
}, []);
const allRelevantData = Object.entries(forecasts).map(([key, value]) => {
const dateTime = new Date(value.dt * 1000);
const day = dateTime.getDay();
const item = {
day: day,
temp: Math.round(value.main.temp),
weatherMetaData: value.weather[0],
};
return item;
});
return filteredForecasts && filteredForecasts.map(({ day, temp, weatherMetaData }) => {
return (
<div className="weather-card">
<div className="day-temperature-container">
<span className="day">{day}</span>
<span className="temperature">{temp}</span>
</div>
<div className="weather-description">
<span
className="icon weather"
style={{
background: `url(http://openweathermap.org/img/wn/${weatherMetaData.icon}.png)`,
}}
/>
<p>{weatherMetaData.description}</p>
</div>
</div>
);
});
};
export default WeatherCard;
import openWeatherConfig from '../../config/apiConfig';
const {baseUrl, apiKey, londonCityId} = openWeatherConfig;
export function getForecast(cityId = londonCityId) {
return fetch(`${baseUrl}/forecast?id=${cityId}&units=metric&appid=${apiKey}`)
.then(res => res.json());
}
问题
useEffect
仅当它是一个空数组依赖项时才在挂载上运行,在这种情况下,预测很可能是空的。
解决方案
filteredForecast
是 forecast
状态的导数 属性。将其从状态中删除并在没有 React.useEffect
.
的情况下使用它
const allRelevantData = Object.entries(forecasts).map(([key, value]) => {
const dateTime = new Date(value.dt * 1000);
const day = dateTime.getDay();
const item = {
day: day,
temp: Math.round(value.main.temp),
weatherMetaData: value.weather[0],
};
return item;
});
let filteredForecasts = null;
if (forecasts.length) {
filteredForecasts = Array.from(
new Set(allRelevantData.map((a) => a.day))
).map((day) => {
return allRelevantData.find((a) => a.day === day);
});
return /** JSX **/
您正在将一个空的依赖项数组传递给您的第二个(过滤预测)useEffect 调用,这意味着它将 运行 仅在组件安装时才会执行。如果您的第一个效果尚未返回,您过滤的预测将永远不会看到任何数据。
您可能根本不需要第二次 useEffect 调用。只需在预测返回第一个效果时计算它。
我正在使用 OpenWeatherAPI,我的获取工作正常。我能够使用 State 将成功获取的数据放入状态。控制台日志出现,我可以看到在网络选项卡中发出的请求。
但是发生了一些有趣的事情,我的 .map()ed 数据并没有像我预期的那样每次都呈现。我将编写代码,按保存,它会显示在屏幕上。但是,如果我刷新页面或重新启动服务器,它就不会出现。有时会在刷新几次后出现。
我很可能在挂钩系统上做错了什么。请指出我做错了什么。
我不能在 promise 解决后直接使用我放入 state 的列表,我需要过滤掉我刚刚在 state 中设置的响应,只得到我需要的 keys/vals 因此你为什么查看 filteredForecasts
的第二个状态。为什么它只是偶尔定期工作?我觉得我有所有正确的 null 检查 if 语句,但它仍然没有按预期工作...
import React from "react";
import WeatherCard from '../WeatherCard';
import "./WeatherList.scss";
const WeatherList = (props) => {
return (
<div className="weather-list-container">
<WeatherCard />
</div>
);
};
export default WeatherList;
import React, { useState, useEffect } from "react";
import "./WeatherCard.scss";
import { getForecast } from "../../api/GET/getForecast";
const WeatherCard = () => {
const [forecasts, setForecasts] = useState([]);
const [filteredForecasts, setFilteredForecasts] = useState([]);
useEffect(() => {
getForecast()
.then((res) => {
const { list } = res;
setForecasts(list);
})
.catch((err) => {
console.log(err);
});
}, []);
useEffect(() => {
if (forecasts.length) {
const uniqueForecasts = Array.from(
new Set(allRelevantData.map((a) => a.day))
).map((day) => {
return allRelevantData.find((a) => a.day === day);
});
setFilteredForecasts(uniqueForecasts);
}
}, []);
const allRelevantData = Object.entries(forecasts).map(([key, value]) => {
const dateTime = new Date(value.dt * 1000);
const day = dateTime.getDay();
const item = {
day: day,
temp: Math.round(value.main.temp),
weatherMetaData: value.weather[0],
};
return item;
});
return filteredForecasts && filteredForecasts.map(({ day, temp, weatherMetaData }) => {
return (
<div className="weather-card">
<div className="day-temperature-container">
<span className="day">{day}</span>
<span className="temperature">{temp}</span>
</div>
<div className="weather-description">
<span
className="icon weather"
style={{
background: `url(http://openweathermap.org/img/wn/${weatherMetaData.icon}.png)`,
}}
/>
<p>{weatherMetaData.description}</p>
</div>
</div>
);
});
};
export default WeatherCard;
import openWeatherConfig from '../../config/apiConfig';
const {baseUrl, apiKey, londonCityId} = openWeatherConfig;
export function getForecast(cityId = londonCityId) {
return fetch(`${baseUrl}/forecast?id=${cityId}&units=metric&appid=${apiKey}`)
.then(res => res.json());
}
问题
useEffect
仅当它是一个空数组依赖项时才在挂载上运行,在这种情况下,预测很可能是空的。
解决方案
filteredForecast
是 forecast
状态的导数 属性。将其从状态中删除并在没有 React.useEffect
.
const allRelevantData = Object.entries(forecasts).map(([key, value]) => {
const dateTime = new Date(value.dt * 1000);
const day = dateTime.getDay();
const item = {
day: day,
temp: Math.round(value.main.temp),
weatherMetaData: value.weather[0],
};
return item;
});
let filteredForecasts = null;
if (forecasts.length) {
filteredForecasts = Array.from(
new Set(allRelevantData.map((a) => a.day))
).map((day) => {
return allRelevantData.find((a) => a.day === day);
});
return /** JSX **/
您正在将一个空的依赖项数组传递给您的第二个(过滤预测)useEffect 调用,这意味着它将 运行 仅在组件安装时才会执行。如果您的第一个效果尚未返回,您过滤的预测将永远不会看到任何数据。
您可能根本不需要第二次 useEffect 调用。只需在预测返回第一个效果时计算它。