Jkaram
Jkaram

Reputation: 933

React Async Function wrapped in a UseEffect

I am confused on how an async function works.

The console.log returns an error because the data.rates does not exist yet. But I thought because the useEffect function is async anything under it would be called after the async is over.

function App() {
  const [data, setData] = useState();

  useEffect(() => {
    (async () => {
      const result = await axios.get(
        "https://open.exchangerate-api.com/v6/latest"
      );
      setData(result.data);
    })();
  }, []);

  console.log(data.rates); <-- Error data.rates does not exist
  return <div>{!data ? "Loading..." : "Hello"}</div>;
}

Upvotes: 0

Views: 272

Answers (3)

jubalm
jubalm

Reputation: 817

Your assumption is actually correct, useEffect in this scenario will run when the Component is mounted that means console.log will be called twice--first with initial value (which is undefined), second is after useEffect performed the side-effect when data is actually set (setData) after the request is fulfilled. You would typically provide a "loading" state while data is stale.

function App() {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState();

  useEffect(() => {
    (async () => {
      setLoading(true);
      const result = await axios.get(
        "https://open.exchangerate-api.com/v6/latest"
      );
      setLoading(false);
      setData(result.data);
    })();
  }, []);

  if (loading) return <div>Fetching data...</div>

  return <div>Hello</div>;
}

Upvotes: 1

Ramesh Reddy
Ramesh Reddy

Reputation: 10662

I feel like none of the answers actually answer the question.

useEffect doesn't stop the flow of execution, it doesn't matter what you're doing inside the callback passed to it. So the console.log(data.rates) gets executed and then once the component is mounted the callback passed to useEffect is executed. Since the state is being changed in the callback(setData(result.data)) this triggers a re-render and this time you should see that the correct value is logged without any errors.

Upvotes: 2

Sagar Kulkarni
Sagar Kulkarni

Reputation: 503

Try doing this (I've kind of created a workaround)

function App() {
    const [data, setData] = useState();

    useEffect(()=>{
        const setObtainedData=async()=>{
            const result = await axios.get("https://open.exchangerate-api.com/v6/latest");
            setData(result.data);
        };
        setObtainedData();
    },[]);

    if(data){
        console.log(data.rates);
    }
    return <div>{!data ? "Loading..." : "Hello"}</div>;
};

Upvotes: 0

Related Questions