Search code examples
javascriptreactjses6-promise

Waiting for function with Promises all


I am using the code from here to load a bunch of .csv files. Once these are loaded, I then want to render a react component. I have posted my method below that is inside a datareader.js. I am trying to figure out how to best call this method from a separate component that calls this and waits for it to complete before proceeding.

export async function LoadParkingTicketsData() {
  let urls = [
    "./data/2016.csv",
    "data/2017.csv"
  ];

  Promise.all(
    //pass array of promises to Promise.all
    urls //you have an array of urls
      .map(
        //map urls to promises created with parse
        (url) =>
          new Promise(
            (
              resolve,
              reject //create one promise
            ) =>
              Papa.parse(url, {
                download: true,
                complete: resolve, //resolve the promise when complete
                error: reject, //reject the promise if there is an error
              })
          )
      )
  )
    .then(function (results) {
      **console.log(results[0]);** // log result from file 1
      console.log(results[1]); // log result from file 2
    })
    .catch(
      //log the error
      (err) => console.warn("Something went wrong:", err)
    );
}

I am assuming I will have to do something inside useEffect() but no matter how I call this method, the execution continues and ends up calling ** line after. Can someone show me how to best do this so the data load happens and until then it waits.

export function TimeOfDayTickets() {

  const [isLoading, setLoading] = useState(true);

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

  if (isLoading) {
    return <div className="App">Loading...</div>;
  }
  return <Line options={options} data={chartData} />;
}

Solution

  • Perhaps this is what you want to do? let me know if that helps

     export function TimeOfDayTickets() {
      const [data, setData] = useState(null);
      const [isLoading, setIsLoading] = useState(true);
    
    
      useEffect(() => {
        LoadParkingTicketsData().then((res) => {
          setData(res);
          
        }).finally(() => {
          setIsLoading(false);
        })
      }, []);
    
      if (isLoading) {
        return <div className="App">Loading...</div>;
      }
      return <Line options={options} data={data} />;
    }
    

    Note: finally will run even if the function is unable to get the data, therefore, isLoading will be set to false and the component Line will render, if you are passing the data state to Line, you should handle inside it what happens if there is no data, for example, rendering a message like "No data available" or something.