Back to list
ReactasyncawaitAPIPromise

[React][API] Is async/await in Both API and UI Redundant?

API modules and React components both use await for different reasons - network response vs returned Promise - so dropping either one breaks the data path to the screen.

1. Environment

  • OS: Windows 11 / macOS
  • Language: JavaScript (ES8+)
  • Frontend library: React.js (v18+)
  • IDE: Visual Studio Code (VS Code)

2. Problem

After learning async / await, one real-world question shows up often:

“The API function already waits with async/await and returns data. Why must the React UI component await that function again? Isn - t that doing the same work twice|–

Short answer: it is not redundant. Below is how the two awaits serve different roles.

Related: Promise on every API call

3. Cause

Clean architecture usually splits API and UI into separate files. That split is why “duplicate wait|–feels plausible:

|–getScenarios()` already waited for the server - why wait again in the component|–

File 1 |–API module

// api.js
export async function getScenarios() {
  // 1. Wait here once
  const response = await axios.get('/api/scenarios/');
  return response.data;
}

File 2 |–React UI

async function loadData() {
  // 2. Wait again here? (feels duplicated)
  const scenarios = await getScenarios();
  setScenarios(scenarios); // update UI state
}

4. Solution

1) Same keyword, different “what|–and “why|–

They are not two copies of one wait. Each waits for a different thing, for a different purpose.

First wait |–inside the API function

  • Where: await axios.get(...) inside getScenarios
  • Waits for: the HTTP response to arrive
  • Why: the frontend must finish the network round-trip with the backend before it has real data

Second wait |–inside the UI component

  • Where: await getScenarios() in the component
  • Waits for: that API function to resolve its Promise with the result array
  • Why: the UI must receive the processed payload before it can update state and re-render

2) Food-delivery analogy

  1. API function (courier): Goes to the restaurant (backend) and waits until cooking is done (await axios.get).
  2. UI component (customer): Waits until the courier rings the doorbell with the food (await getScenarios).

3) What if you drop either await?

  1. Omit await in the API function |–You hand the UI an empty shell before the backend data arrives.
  2. Omit await in the UI |–The API is still fetching, but the screen finishes rendering empty. When data arrives later, the UI never updates from that missed wait.

5. Summary

Both async/await usages are intentional and necessary in their own layer:

  • API function: infrastructure that fetches data - waits on the network.
  • UI component: consumer that shows data - waits until that infrastructure finishes.

Along an async call chain, you must keep await connected all the way to the outermost consumer so backend data reaches the user?’s screen safely.

Related posts