Ошибка типа: Не удается прочитать свойство «0» неопределенного в react

#javascript #reactjs #weather-api

Вопрос:

Я разрабатываю приложение «Погода» в react. Это учебный проект. Я получаю ошибку.

Я использую 3 компонента.

App.js:

 <WeatherApiAddressProvider>
  <WeatherCity />
</WeatherApiAddressProvider>
 

WeatherApiAddressProvider(Контекстный API):

 const setApiAddress = (city) => {
  const address = `https://api.openweathermap.org/data/2.5/weather?q=${city}amp;appid=7b7503a2aa9ca872738c7213619a72f5`;
  return address;
};

export const WeatherApiAddressProvider = ({ children }) => {
  return (
    <WeatherContext.Provider value={setApiAddress}>
      {children}
    </WeatherContext.Provider>
  );
};
 

WeatherCity.js:

 const setApiAddress = useContext(WeatherApiAddressContext);

const [city, setCity] = useState("");

const handleChange = (e) => {
  setCity(e.target.value);
};
return (
  <div>
    <div className="container">
      <div className="row">
        <div className="col">
          <select
            className="form-select mb-3"
            aria-label="Default select example"
            value={city}
            onChange={handleChange}
          >
            <option className="placeholder" value="">
              Please select a city
            </option>
            <option value="adana">Adana</option>
            ...
          </select>
        </div>

        <div className="col">
          <div className="p-5">
            <WeatherDetail setApiAddress={setApiAddress} city={city} />
          </div>
        </div>
      </div>
    </div>
  </div>
);
 

WeatherDetail.js:

 const [weatherInfo, setWeatherInfo] = useState({});

let imgCode = weatherInfo.weather[0].icon;

useEffect(() => {
  axios.get(city ? setApiAddress(city) : "").then((response) => {
    setWeatherInfo(response.data);
  });
}, [city, setApiAddress]);

return (
  <div>
    {city !== "" amp;amp; (
      <div className="card">
        <img
          className="card-img-top"
          src={`https://openweathermap.org/img/wn/${imgCode}.png`}
        />
        <div className="card-body">
          <h5 className="card-title">{weatherInfo.name}</h5>
          <p className="card-text">
            Some quick example text to build on the card title and make up the
            bulk of the card's content.
          </p>
        </div>
      </div>
    )}
    {}
  </div>
);
 

Как вы знаете, WeatherApiAddressProvider setApiAddres функция throw, WeatherCity переменная throw city. WeatherDetail получите их и получите данные с помощью axios weatherapi .

Ошибка, которую я получаю:

Ошибка типа: Не удается прочитать свойство ‘0’ неопределенного(пусть imgCode = weatherInfo.погода[0].значок)

Решения, которые я пробовал:

  • Я зарегистрировал полученные данные( weatherInfo или response.data ) и увидел, что эти данные являются объектом. Затем я определил initialState(weatherInfo) как объект, но это не решило проблему.
  • Я создал объект, подобный полученным данным в initialState . Но это не решило проблему.

Я хочу показать репрезентативное изображение погоды и сведения о погоде в WeatherDetail.js. Как я могу это сделать?

Комментарии:

1. @PatrickEvans Я продолжал получать ошибку при создании объекта, подобного полученным данным(в состоянии weatherInfo)

Ответ №1:

Измените выражение следующим образом в своем WeatherDetails.js

   let imgCode = weatherInfo amp;amp; weatherInfo.weather.length >0 amp;amp; weatherInfo.weather[0].icon
 

Комментарии:

1. Новая ошибка: Ошибка типа: Не удается прочитать свойство «длина» неопределенного

Ответ №2:

weatherInfo.weather на данный момент не определено:

 const [weatherInfo, setWeatherInfo] = useState({});

let imgCode = weatherInfo.weather[0].icon;
 

Я полагаю, что вы хотите установить значение imgCode после того, как позвоните setWeatherInfo .

Комментарии:

1. Да, я хочу этого. Ваше решение не сработало. Я и раньше так думал. Я назначил IMG-код в useEffect, но это не сработало.

Ответ №3:

Прямо здесь

 const [weatherInfo, setWeatherInfo] = useState({});

let imgCode = weatherInfo.weather[0].icon;
 

Вы пытаетесь получить первый элемент массива, которого нет в пустом объекте weatherInfo , который вы только что создали. Самым простым решением для этого было бы использовать необязательную цепочку и изменить weatherInfo.weather[0].icon ее на weatherInfo?.weather[0]?.icon «однако это не идеально», потому что у вас была бы разорвана ссылка на изображение.

Вы могли бы создать другое государство с

 const [imgCode, setImgCode] = useState('');
 

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

 { imgCode amp;amp; <img
   className="card-img-top"
   src={`https://openweathermap.org/img/wn/${imgCode}.png`}
  /> 
} 

 

Комментарии:

1. К сожалению, ничего не изменилось.

2. Вы уверены, что weatherInfo содержит свойство погода, которое является массивом? Вы можете сделать « useEffect( () => { setImgCode(weatherInfo?.погода[0]?.значок) }, [weatherInfo])`, чтобы убедиться, что ваш IMG-код соответствует объекту, который вы получаете в результате вызова api

3. Weatherinfo-это объект, содержащий массив, называемый weather. Я не могу получить доступ к объекту значка первого элемента массива погоды. Я также попробовал другой код, который вы упомянули, к сожалению, он не решает проблему.

Ответ №4:

Это было причиной ошибки:

 useEffect(() => {
    axios.get(city ? setApiAddress(city) : "")
        .then((response) => {
            setWeatherInfo(response.data);
        })
}, [city, setApiAddress]);
 

Я изменил код следующим образом:

 useEffect(() => {
    axios.get(city ? setApiAddress(city) : "")
        .then((response) => {
            setWeatherInfo(response.data.weather[0]);
        })
}, [city, setApiAddress]);
 

Я буду использовать состояние по мере необходимости.