#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]);
Я буду использовать состояние по мере необходимости.