Проблема с асинхронностью 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);
};
→ Ссылка