koda
koda

Reputation: 3

React Hooks changing state of an array inside of asycn function after useEffect call

I have three states here I am changing them inside of an 'async function. Two of them changes perfectly but there is also an array state and nothing happens to it. I really want to learn why this is happening.

function RandomCocktail () {
    const [item, setItem] = useState('');
    const [drinkImage, setDrinkImage] = useState('');
    const [ingredients, setIngredients] = useState([]);

    function sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    };

    async function DrinkChange() {
      setItem("Loading..");
      try {
        let res = await fetch('https://www.thecocktaildb.com/api/json/v1/1/random.php');
        let result = await res.json();
        console.log(result);
        await sleep(500);
        // Below two states changes perfectly
        setItem(result["drinks"][0]["strDrink"]);
        setDrinkImage(result["drinks"][0]["strDrinkThumb"]);
        let i = 1;
        let t = [];
        while(result["drinks"][0]["strIngredient"+i.toString()] !== null)
        {
          console.log(result["drinks"][0]["strIngredient"+i.toString()]);
          t.push({id: i, dr: result["drinks"][0]["strIngredient"+i.toString()]});
          i++;
        }
        //when it comes to changing the array state nothing happens
        setIngredients([...t]);
        console.log(t);
        //logs all the ingredients
        console.log(ingredients);
        //logs []
      } catch (error) {
        setItem('Error');
      }  
    };

    

    useEffect(() => {
      DrinkChange();
    },[]);
  
    return(
      <CocktailPage item={item} drinkImage={drinkImage}/>
    );  
}

export default RandomCocktail;

Upvotes: 0

Views: 72

Answers (1)

Suraj Rane
Suraj Rane

Reputation: 161

In react setState operations are asynchronous in nature so if you try to console log immediately after setting a state you can get the previous state value

Your state is getting set properly just console log the state value outside the function to print the updated state.

import React, { useEffect, useState } from "react";

function RandomCocktail() {
  const [item, setItem] = useState("");
  const [drinkImage, setDrinkImage] = useState("");
  const [ingredients, setIngredients] = useState([]);

  function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }

  async function DrinkChange() {
    setItem("Loading..");
    try {
      let res = await fetch(
        "https://www.thecocktaildb.com/api/json/v1/1/random.php"
      );
      let result = await res.json();
      await sleep(500);
      // Below two states changes perfectly
      setItem(result["drinks"][0]["strDrink"]);
      setDrinkImage(result["drinks"][0]["strDrinkThumb"]);
      let i = 1;
      let t = [];
      while (result["drinks"][0]["strIngredient" + i.toString()] !== null) {
        t.push({
          id: i,
          dr: result["drinks"][0]["strIngredient" + i.toString()],
        });
        i++;
      }
      //when it comes to changing the array state nothing happens
      setIngredients([...t]);
      //logs []
    } catch (error) {
      setItem("Error");
    }
  }

  console.log("ingredients", ingredients);

  useEffect(() => {
    DrinkChange();
  }, []);

  return(
    <CocktailPage item={item} drinkImage={drinkImage}/>
  );  
}

export default RandomCocktail;

Upvotes: 1

Related Questions