Matt
Matt

Reputation: 115

React, onClick only works after second click, Axios, Async/Await

I must be missing something very straight forward. I am trying to make an axios GET request and then setState in an async/await function, I have also tried fetch().then(). The console.log() returns undefined unless I click getData() twice or put it in a separate onClick() event. I think the state is being set correctly but the console.log() doesn't perform as I expect it. Is there a way to console.log() in the same function as the axios request? As always, any help is greatly appreciated. Thanks!

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

const SalesGraph = () => {
  const [retrievedData, setretrievedData] = useState();

  const getData = async () => {
    try {
      const salesData = await axios.get("http://localhost:5000/sales");
      await setretrievedData(salesData);
      console.log(retrievedData);
    } catch (err) {
      console.log(err);
    }
  };
  const showState = () => {
    console.log(retrievedData);
  };
  return (
    <div>
      <button onClick={getData}>Graph</button>
      <button onClick={showState}>showState</button>
    </div>
  );
};
export default SalesGraph;

Upvotes: 2

Views: 2130

Answers (2)

wangdev87
wangdev87

Reputation: 8751

setretrievedData is the asynchronous method and you can't get the updated value of retrievedData immediately after setretrievedData.

You need to get it in the useEffect by adding a dependency.

useEffect(() => {
  console.log(retrievedData);
}, [ retrievedData ]);

Upvotes: 2

Shmili Breuer
Shmili Breuer

Reputation: 4147

All setters for react useState are async so even if you await your setretrievedData it will go on to the next line even before it is done.

To run any code only after the setter is done you need to add a useEffect and pass the state to watch as the 2nd arg

Upvotes: 1

Related Questions