Невозможно получить доступ / управлять данными из API погоды с помощью axios с useEffect в React.js

Я использую axios для получения данных API погоды с помощью useEffect.

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { Header } from './Header';

export const CurrentCity = () => {
  const [weather, setWeather] = useState({});

  console.log('weather', weather);
  console.log(weather.weather[0].icon);

  useEffect(() => {
    async function getData() {
      const url = `https://api.openweathermap.org/data/2.5/weather?q=Berlin&appid=${process.env.REACT_APP_WEATHER_KEY}`;
      try {
        const response = await axios.get(url);
        setWeather(response.data);
      } catch (err) {
        console.log(err);
      }
    }
    getData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  return (
    <div>
      <Header api={weather} />
    </div>
  );
};

Это результат console.log (данные):

{coord: {…}, weather: Array(1), base: "stations", main: {…}, visibility: 10000, …}
coord: {lon: 13.41, lat: 52.52}
weather: Array(1)
0: {id: 802, main: "Clouds", description: "scattered clouds", icon: "03n"}
length: 1
__proto__: Array(0)
base: "stations"
main: {temp: 278.43, feels_like: 270.3, temp_min: 276.48, temp_max: 280.37, pressure: 1009, …}
visibility: 10000
wind: {speed: 8.7, deg: 270, gust: 13.9}
clouds: {all: 40}
dt: 1584060559
sys: {type: 1, id: 1275, country: "DE", sunrise: 1584077086, sunset: 1584119213}
timezone: 3600
id: 2950159
name: "Berlin"
cod: 200
__proto__: Object

Если я console.log данные, которые я получаю

console.log('weather', weather);

console.log(weather.weather[0].icon);

в сообщениях об ошибках говорится, что он не может прочитать свойство [0],

или, например, если я попытаюсь проникнуть глубже в "ветер",

 console.log(weather.wind.speed);

он говорит, не может прочитать свойство скорости.

Если это массив, к которому я хочу получить доступ, я бы использовал [0] или, если это объект, я бы использовал точечную нотацию.

Кроме того, я передаю данные, полученные от axios, в Header.js.

import React from 'react';

export const Header = props => {
  console.log(props.api.name);
  return (
    <div>
      <h1>{props.api.name}</h1>
    </div>
  );
};

То же самое происходит, когда я пытаюсь глубже изучить другие данные.

Я хотел бы узнать, что мне не хватает, заранее всем спасибо! А также хочу знать, в чем разница между 1 и 2, и какой из них я должен использовать в текущей ситуации.

  1. const [weather, setWeather] = useState({});
  2. const [weather, setWeather] = useState(null);

person JongHyeok Lee    schedule 13.03.2020    source источник
comment
Когда вы вызываете console.log(weather.weather[0].icon);, погода просто инициализируется на {}, поэтому вы видите сообщение об ошибке в консоли.   -  person sam    schedule 13.03.2020
comment
Разница между 1 и 2 заключается в том, что weather инициализируется как {} в 1-м и null во 2-м.   -  person Dev    schedule 13.03.2020
comment
@JongHyeokLee также см. stackoverflow.com/help/someone-answers   -  person TenTen Peter    schedule 14.03.2020


Ответы (2)


Ваш код правильный, но, как сказали ребята, объект weather изначально будет установлен как пустой объект {}, поэтому вам просто нужно сначала его проверить.

const App = () => {

  const [weather, setWeather] = useState(null) // change it to null for easier check

  // useEffect() ...

  if (!weather) {
    return <div>Loading indicator</div>
  }

  return (
    <div className="App">
      <Header api={weather} />
    </div>
  )
}

 Изменить романтик-бартик-9oyk3

person awran5    schedule 13.03.2020
comment
Я думаю, проблема здесь console.log('weather', weather); console.log(weather.weather[0].icon); PO регистрирует то, чего не существует. - person Junius L.; 13.03.2020
comment
см. codeandbox.io/s/ - person Junius L.; 13.03.2020
comment
Да, я это понимаю, но из того, что я понимаю, основная проблема заключалась в том, что он не мог прочитать данные из Header компонента, поэтому он попытался log это. Удалите этот log и проверьте возврат, вы получите ту же ошибку. - person awran5; 13.03.2020
comment
@JuniusL. Я имею в виду , не могли бы вы показать свое решение, если я ошибаюсь? - person awran5; 13.03.2020
comment
Я не говорю, что вы ошибаетесь, я просто говорил об ошибке консоли, поскольку OP пытался получить доступ к несуществующему свойству. - person Junius L.; 13.03.2020
comment
@JuniusL. Так почему же голос против? Ваш второй подход как раз о том, что я сделал. - person awran5; 13.03.2020
comment
Ой, извините тогда, nvm, я так подумал, потому что получил это после вашего первого комментария. - person awran5; 13.03.2020
comment
Спасибо, народ! Помогли исправить мой код! Большое спасибо! - person JongHyeok Lee; 13.03.2020
comment
@JongHyeokLee Спасибо. На самом деле JuniusL answer 'имеет лучший подход, вы можете использовать индикатор загрузки и обработку ошибок в своем приложении, как он опубликовал. - person awran5; 13.03.2020

Вы получаете эту ошибку, потому что пытаетесь получить доступ к ключу, которого нет в объекте. В следующей погоде устанавливается пустой объект.

// remove this from your code
console.log('weather', weather);
// this will throw an error, since weather is an empty object.
console.log(weather.weather[0].icon);

import React, { useEffect, useState } from "react";
import axios from "axios";
import { Header } from "./Header";

export const CurrentCity = () => {
  const [weather, setWeather] = useState({});

  useEffect(() => {
    async function getData() {
      const url = `https://api.openweathermap.org/data/2.5/weather?q=Berlin&appid=${
        process.env.REACT_APP_WEATHER_KEY
      }`;
      try {
        const response = await axios.get(url);
        setWeather(response.data);
      } catch (err) {
        console.log(err);
      }
    }
    getData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  return (
    <div>
      <Header api={weather} />
    </div>
  );
};

Затем в заголовке проверьте свои данные, не думайте, что вы всегда будете получать нужные данные.

import React from "react";

export const Header = props => {
  console.log(props);
  return (
    <div>
      {/* here validate your data */}
      <h1>{props && props.api && props.api.name}</h1>
    </div>
  );
};

Вы также можете добавить загрузчик, чтобы показать пользователю, что вы загружаете данные с сервера.

export const CurrentCity = () => {

  const [weather, setWeather] = useState({});
  const [isLoading, setIsLoading] = useState(true);
  const [isError, setIsError] = useState(false);

  useEffect(() => {

    async function getData() {

      const url = `https://api.openweathermap.org/data/2.5/weather?q=Berlin&appid=${
        process.env.REACT_APP_WEATHER_KEY
      }`;
      try {

        const response = await axios.get(url);
        setWeather(response.data);
        setIsLoading(false);

      } catch (err) {

        setIsError(true);
        setIsLoading(false);
        console.log(err);

      }

    }
    getData();
    // eslint-disable-next-line react-hooks/exhaustive-deps

  }, []);

  return (
    <>
      {isLoading ? (
        <h1>Loading ...</h1>
      ) : isError ? (
        <p>Something went wrong</p>
      ) : (
        <Header api={weather} />
      )}
    </>
  );

};
person Junius L.    schedule 13.03.2020
comment
Спасибо за помощь! Я очень это ценю! Мой код заработал! - person JongHyeok Lee; 13.03.2020
comment
@JongHyeokLee см. stackoverflow.com/help/someone-answers - person Junius L.; 27.03.2020