Проблема с асинхронностью useState React
Всем привет. Пишу программу погодную на реакте и столкнулся бедой с хуком useState. а именно то что он асинхронен и дату которую я должен получить в state получается на первый клик сабмита null а на второй уже отрабатывает норм. Я написал некоторые функции и вызываю их в главной функции. Код немного сокращу чтобы не было лишней воды
const useForecast = () => {
const [forecast, setForecast] = useState(null);
// функция где я меняю state
const gatherForecastData = async data => {
const currentDay = await getCurrentDayForecast(data.consolidated_weather[0], data.title);
const currentDayDetails = await getCurrentDayDetailedForecast(data.consolidated_weather[0]);
await setForecast({ currentDay, currentDayDetails});
setLoading(false);
};
// главная функция где вызываются другие функции
const submitRequest = async location => {
setLoading(true);
setError(false);
const response = await getWoeid(location);
if (!response?.woeid) return;
const data = await getForecastData(response.woeid);
if (!data) return;
gatherForecastData(data);
console.log(data);
// эта дата которая идет с api отрабатывает нормально
console.log(forecast);
// эта же дата только которая должна быть в state выдает null
};
Как тут избавиться от этой ошибки?
Ответы (2 шт):
Автор решения: p1uton
→ Ссылка
setState - асинхронная функция
Это значит, что после вызова setForecast значение forecast изменится не сразу и console.log будет возвращать старое значение.
Чтобы дождаться изменения значения forecast нужно использовать useEffect:
useEffect(() => {
console.log(forecast);
}, [forecast]);
Автор решения: Armen
→ Ссылка
const useForecast = () => {
const [forecast, setForecast] = useState(null);
console.log(forecast) после ререндера будет новое значение
useEffect(() => {
если надо что то сделать после ререндера
}, [forecast])
// функция где ты просто дастаеш данные
const gatherForecastData = async data => {
const currentDay = await something
const currentDayDetails = await something2
return { currentDay, currentDayDetails }
};
// главная функция где вызываются другие функции
const submitRequest = async location => {
setLoading(true);
setError(false);
const response = await getWoeid(location);
if (!response?.woeid) return;
const data = await getForecastData(response.woeid);
if (!data) return;
const res = await gatherForecastData(data);
setForecast(res);
// если нужен именно по каким то причинам forecast то как и советовали useEffect
// если просто значение то на данный момент это все еще **res**
setLoading(false);
};