Reactjs array push not working in async function

Viewed 58
 const [cart, setCart] = useState({})

    useEffect(()=>{
        const items = JSON.parse(localStorage.getItem('cart')); // return [5,6]
        let array = [];
        if(items && items.length){
            items.map(function (cart_id){
                getPack(cart_id).then((result)=>{
                    array.push(result.data) // not working
                    console.log(result.data) // got data as object!
                })
            })
            setCart(array);
            console.log(array); // return empty
        }
    }, []);

    const getPack = async(id) => {
        return await Api.Get('getPack', false, false, id); // get data from api
    }

What I trying to do is after get data from api from async function called getPack set it to object. I got data from getPack but I want to set it to array, I used array.push but it's not working. Any idea what is wrong?

3 Answers

You return promise which is async, so your code console.log(array); will be executed before you get the response from your endpoint and entering inside callback in then. In other words, there is no guarantee that your code after getPack(cart_id).then will be execute when array is fields because it is asynchronous.

As an option create an additional state for your array instead of declaring it inside the useEffect:

const [array, setArray] = useState([])
useEffect(()=>{
    const items = JSON.parse(localStorage.getItem('cart')); // return [5,6]
    if(items && items.length){
        items.map(function (cart_id){
           getPack(cart_id).then((result)=>{
                setArray(oldArray => [...oldArray, result.data]) 
                console.log(result.data)
            })
        })
        console.log(array); // return empty
    }
}, []);

const getPack = async(id) => {
   return await Api.Get('getPack', false, false, id); // get data from api
}

You need to look into the response of "Api.Get" method.

const [cart, setCart] = useState([]) //changed {} to []

useEffect(()=>{
    const items = JSON.parse(localStorage.getItem('cart')); // return [5,6]
    let array = [];
    if(items && items.length){
        items.map(function (cart_id){
            getPack(cart_id).then((result)=>{
                array.push(result) // its working perfect my side
                console.log(result) // got data as object!
            })
        })
        setCart(array);
        console.log(array); // return array of objects
    }
}, []);

const getPack = async(id) => {
    return {data:1} 
    //await Api.Get('getPack', false, false, id); // get data from api
}

This part is not correctly written:

let array = [];
if(items && items.length){
    items.map(function (cart_id){
        getPack(cart_id).then((result)=>{
            array.push(result) // its working perfect my side
            console.log(result) // got data as object!
        })
    })
    setCart(array);
    console.log(array); // return array of objects
}

I haven't got a chance to test this particular piece of code but you'd better try something like:

if(items && items.length){
    let array = items.map(function (cart_id){
        return getPack(cart_id).then((result)=>{
            return result.data;
        })
    })
    setCart(array);
}

This way you loop items and assign to each new 'array' element the result of each promise resolved from the async method 'getPack(cart_id)'

Related