Home > OS >  Why do I need to use async await to call a async function in React while it doesn't need in pur
Why do I need to use async await to call a async function in React while it doesn't need in pur

Time:08-29

I did two tests:

The first test is in a pure JS file in which I called the async await function right after I created the function, it prints the correct data. The code:

const fetchData = async () => {
  const res = await fetch('https://601caf791a9c220017060c02.mockapi.io/api/v1/Events');
  const data = await res.json();
  console.log(data);
}

fetchData()

While the second test I created the async await function inside a JS file in the React application, and then import that async function into another component and called it when the component did mount. But this time I got a Promise instead of the actual data. The code:

api.js:

export const fetchData = async () => {
  const res = await fetch(
    "https://601caf791a9c220017060c02.mockapi.io/api/v1/Events"
  );
  const data = await res.json();
  return data;
};

App.js:

import { useEffect } from 'react';
import { fetchData } from './api';

export default function App() {
  useEffect(() => {
    const results = fetchData();
    console.log(results);
  }, [])

  return (
    <div className="App">
      <h1>Hello world!</h1>
    </div>
  );
}

If I use another async await to call the fetchData function in the App component, it will retun the actual data.

I understand the async function will always return a Promise but why in the first test we don't need to add another async await when calling the fetchData function while it needs the async await to call the function inside the React application in order to get the actual data?

CodePudding user response:

If you return the data in the first case and the log it, it will behave in the same way as case 2.

const fetchData = async () => {
  const res = await fetch('https://601caf791a9c220017060c02.mockapi.io/api/v1/Events');
  const data = await res.json();
  return data;
}

console.log(fetchData());

The reason the actual data is printed in the first case is that you are logging the data after first two lines when the promises are resolved.

For the second case, fetchData() is called which returns a promise because the promise is not resolved or rejected yet, then, immediately the next line is executed and the promise is logged because the promise is still not resolved or rejected.

CodePudding user response:

You're not comparing apples to apples.

In the first case, you're calling console.log(data) inside the async function, which doesn't care about the outside environment since its scope is async.

With the other example, you're calling console.log on the return value of the function, which is a Promise because async functions always return promises. You are also calling console.log before the Promise is resolved, so how could you get any meaningful data if it doesn't exist yet?

If you changed the first to

const fetchData = async () => {
  const res = await fetch('https://601caf791a9c220017060c02.mockapi.io/api/v1/Events');
  const data = await res.json();
  return data;
}

const data = fetchData();
console.log(data);

you'd get the same result as the second example.

If you want to get the actual data inside your useEffect, you need to either use async/await or .then().

import { useEffect } from 'react';
import { fetchData } from './api';

export default function App() {
  useEffect(() => {
    (async () => {
      const results = await fetchData();
      console.log(results);
    })();
  }, [])

  return (
    <div className="App">
      <h1>Hello world!</h1>
    </div>
  );
}

(note that the callback in useEffect itself cannot be async)

CodePudding user response:

It doesn't matter if the promise is resolved or not in async/await, a brand new Promise is returned which has to be resolved in the calling function which is not the case while using fetch if the returned value is resolved.

Even if the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

Thinks of it in layman's term as async makes the function return a new promise always whereas fetch just affects the variable which it returns.

Please see docs for more reference

  • Related