Невозможно получить значение свойства объекта, полученного в результате вызова API, в REACTJS - PullRequest
0 голосов
/ 28 мая 2020

Почему я не могу получить доступ к значению свойства объекта, полученного в результате вызова API?

У меня есть два компонента в приложении React, оба указаны ниже.

Вот первый компонент с именем «Погода»

import React, { useState, useEffect } from "react";
import Styles from "./Weather.module.css";
import WeatherCard from "../Weather Card/WeatherCard.component";

const Weather = () => {
  // Initializing State
  //For Location
  const [location, setLocation] = useState("karachi");
  //For Location
  //For Query
  const [query, setQuery] = useState(location);
  //For Query
  //For Weather Data
  const [weatherData, setWeatherData] = useState({});

  //For Weather Data

  // Initializing State

  // Calling data through api

  useEffect(() => {
    const fetchingData = async () => {
      let url = `https://api.openweathermap.org/data/2.5/weather?q=${query}&appid=6a571911f99d7d02c4974a178ff1d933`;

      let responseFromFetch = await fetch(url); // getting obj of promise.

      let data = await responseFromFetch.json(); // getting api/weather data.

      setWeatherData(data); // setting state that comes from api.
    };

    fetchingData(); // calling func that brings the data
  }, [query]);

  const handleSubmit = (e) => {
    e.preventDefault();
    setQuery(location);
    setLocation("");
  };

  return (
    <>
      <div className={Styles.formContainer}>
        <form onSubmit={handleSubmit}>
          <input
            className={Styles.inputField}
            type="text"
            placeholder="Know Your City Weather!"
            value={location}
            onChange={(e) => setLocation(e.target.value)}
          />
          <button type="submit" className={Styles.button}>
            Search
          </button>
        </form>
      </div>

      <WeatherCard weatherData={weatherData} />
    </>
  );
};

export default Weather;

Хорошо, теперь вот второй Компонент с именем «WeatherCard»

import React, { Component } from "react";
import Styles from "../Whether/Weather.module.css";

export default class WeatherCard extends Component {
  render() {
    const accessObj = this.props.weatherData;

    console.log(accessObj); // getting whole obj - No error,
    console.log(accessObj.name); // getting the value of the key "name" - No error,       accessObj.name isn't an object
    console.log(accessObj.sys); // getting obj - No error,          accessObj.sys is an object
    console.log(accessObj.sys.country); // Not getting the value of key "country" - Error

    if (accessObj !== "undefined") {
      return (
        <>
          <div className={Styles.wrapper}>
            <div className={Styles.weatherContainer}>
              <div className={Styles.cityContainer}>
                <p className={Styles.city}>{accessObj.name}</p>
              </div>

              <div className={Styles.countryContainer}>
                {/* I want here to use the value of the property... But country is not available here.  */}

                <p className={Styles.country}>{accessObj.sys.country}</p>
              </div>

              <div className={Styles.tempContainer}>
                <p className={Styles.temp}>30 C</p>
              </div>

              <div className={Styles.humidityContainer}>
                <p className={Styles.humidity}>100</p>
              </div>
            </div>
          </div>
        </>
      );
    }
  }
}

Вы также можете увидеть ошибку, возникающую в браузере. Ссылка на скриншот: ЗДЕСЬ . Не удалось прикрепить сюда снимок экрана с ошибкой, потому что я новичок в этой платформе! enter image description here

Заранее спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 28 мая 2020

Вы проверяете accessObj !== "undefined", но начальное значение - пустой объект ({}). Начальное значение берется из компонента Погода weatherData={weatherData}. Так что ваше условие if (accessObj !== "undefined") всегда верно. Одно из возможных решений - инициализировать weatherData следующим образом:
const [weatherData, setWeatherData] = useState(null); И выполнить проверку следующим образом: if (accessObj) {} Это условие будет истинным после того, как вы загрузите данные и setWeatherData

0 голосов
/ 28 мая 2020

излишняя фантазия иногда может привести к некоторым проблемам, подобным той, что здесь, в основном проблема в том, что ваш хук useEffect имеет тип void, так как он ничего не возвращает.

...

const fetchingData = () => {
      let url = `https://api.openweathermap.org/data/2.5/weather?q=${query}&appid=6a571911f99d7d02c4974a178ff1d933`;

     return fetch(url)
        .then(res => res.json())
        .then(data => myFunctionThatSetsTheState(data)).catch(console.error)
};

useEffect(() => fetchingData(), [query]);

....
0 голосов
/ 28 мая 2020

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

Добавление условия в console.log в <WeatherCard>, скорее всего, решит вашу проблему.

if(accessObj.sys){ //Will check if the accessObj.sys object is not undefined; if it's not undefined, it will return true and the console.logs will happen.
   console.log(accessObj);
   console.log(accessObj.name); 
   console.log(accessObj.sys);
   console.log(accessObj.sys.country);
}

Для остальной части кода вы хорошо справились, потому что добавили условие для рендеринга, что в основном то, что я поставил выше.

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