【问题标题】:React useEffect not behaving as expected反应 useEffect 的行为不符合预期
【发布时间】:2020-10-26 04:03:46
【问题描述】:

我正在使用 OpenWeatherAPI,我的 fetch 工作正常。我可以使用状态将成功的获取数据放入状态。控制台日志显示出来,我可以看到在网络选项卡中发出的请求。

但是发生了一些有趣的事情,我的 .map() 数据并没有像我期望的那样每次都呈现。我将编写代码,按保存,它将显示在屏幕上。但是,如果我刷新页面或重新启动服务器,它就不会出现。有时它会在几次刷新后显示。

我很可能在钩子系统中做错了什么。请指出我做错了什么。

我不能直接使用我在承诺解决后放入状态的列表,我需要过滤掉我刚刚在状态中设置的响应,只获取我需要的键/值,因此为什么你会看到第二个状态为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 意味着它只会在组件安装时运行一次。如果您希望它有条件地运行,请尝试将 setFilteredForecasts 放入数组中。

标签: javascript reactjs react-hooks use-effect use-state


【解决方案1】:

问题

useEffect 仅在挂载时运行空数组依赖项,在这种情况下,预测很可能为空。

解决方案

filteredForecastforecast 状态的派生属性。将其从状态中删除并在没有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 !但是你这行得通,我现在可以继续编码了!
【解决方案2】:

您将一个空的依赖数组传递给您的第二个(过滤预测)useEffect 调用,这意味着它只会在组件挂载时运行。如果您的第一个效果尚未返回,您过滤后的预测将永远不会看到任何数据。

您可能根本不需要第二个 useEffect 调用。只需在预测返回第一个效果时计算它。

【讨论】:

  • 感谢您的回复,我选择 Prateek 解决方案只是因为我认为将所有这些计算代码都放在 useEffect 中有点不那么优雅。不过还是谢谢!您的逻辑/推理与 Prateek 的几乎相同!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 2021-04-09
相关资源
最近更新 更多