0

My useEffect populates tempStocksData, which is passed into setStockData() when the Promise is fulfilled. As shown in the code below, print out tempStocksData and stockData, which is supposed to be populated since I called setStockData(tempStocksData). You can see that Promise is fulfilled since it executes the prints. However, stockData is empty. For some reason setStockData is not working since stockData is not being populated. Below is the code for reference:

    const [ stockData, setStockData ] = useState([])

    const getStocksData = (stock) => {
        return axios.get(`${BASE_URL}?symbol=${stock}&token=${TOKEN}`).catch((error) => {
            console.error("Error", error.message)
        })
    }

    useEffect(()=> {
        let tempStocksData = []
        const stocksList = ["AAPL", "MSFT", "TSLA", "FB", "BABA", "UBER", "DIS", "SBUX"];
        let promises = [];
        stocksList.map((stock) => {
            promises.push(
                getStocksData(stock)
                .then((res) =>
                
                {tempStocksData.push({
                        name: stock,
                        ...res.data
                    })
                })
            )
        })
        Promise.all(promises).then(()=>{
            console.log(tempStocksData)
            setStockData(tempStocksData)
            console.log(stockData) 
        })   
    }, []) 

Please help me resolve this issue. Let me know if there is something I'm missing or something that I'm doing that is not up to date with versions/dependencies or if I'm doing Promise() js wrong.

1
  • Are you even enterin your "Promise.all" sequence? Commented Sep 30, 2021 at 19:53

3 Answers 3

1

Are you even entering your Promise.all sequence to begin with?

You are already ending the promise by having a .then function after getting the stockdata.

stocksList.map((stock) => {
    promises.push(
        getStocksData(stock)
    )
})

Promise.all(promises).then((result)=>{
    const tempStocks = result.map((stock) => {
        return {
            name: stock.name,
            data: stock.data
        }
     });

console.log(tempStocksData)
setStockData(tempStocksData)
console.log(stockData) 

})   

Note: Above code is untested but is made to show the point

Sign up to request clarification or add additional context in comments.

1 Comment

I tried your implementation, and stockData is still not getting populated
0

Try using the spread operator when you setStockData

like this

    setStockData([...tempStocksData])

1 Comment

stockData is still not getting populated after that
0

Since I've stumbled across this issue today while looking up a setData issue, let me clarify some things. Others have pointed out that your use of promises is probably not what you actually intend to do.

Regardless, it is important to understand that a console.log of stockData inside the same useEffect that issues setStockData (even when the setter is called "before" the logging attempt) will not show the updated data in the console.

This is because all setters from useState are batched together inside useEffect calls and the corresponding getter (stockData in this case) will only reflect the updated value in the next rendering loop. It will, however, be made available when rendering or to any other hooks listening to changes to stockData.

You can find an example implementation on StackBlitz. Note that the console.log will show an empty array even though the view is updated with the API query results.

The code example from StackBlitz reproduced here:

import * as React from 'react';
import './style.css';
import { useState, useEffect } from 'react';
import axios from 'axios';

const TOKEN = 'IAPYYRPR0LN9K0K4';
const BASE_URL = 'https://www.alphavantage.co/query?function=GLOBAL_QUOTE';

export default function App() {
  const [stockData, setStockData] = useState([]);

  const getStocksData = (stock: string) => {
    return axios
      .get<{ 'Global Quote': { [data: string]: string } }>(
        `${BASE_URL}&symbol=${stock}&apikey=${TOKEN}`
      )
      .then((result) => result.data)
      .catch((error) => {
        console.error('Error', error.message);
      });
  };

  useEffect(() => {
    const stocksList = ['AAPL', 'MSFT', 'TSLA'];
    let promises: Promise<void | {
      'Global Quote': { [data: string]: string };
    }>[] = [];
    stocksList.map((stock) => {
      promises.push(getStocksData(stock));
    });
    Promise.all(promises).then((result) => {
      setStockData(result);
      console.log(stockData);
    });
  }, []);
  return <pre>{JSON.stringify(stockData, undefined, '  ')}</pre>;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.