How promise works in React

In React, Promises are a fundamental part of managing asynchronous operations, such as fetching data from an API, handling user input, or performing time-consuming computations. Promises provide a way to represent the eventual completion (or failure) of an asynchronous operation and allow you to handle the result (or error) asynchronously. Here’s a detailed explanation with examples of how Promises work in React. We’ll use the useState and useEffect hooks to demonstrate how to manage asynchronous operations with Promises. Here’s a step-by-step explanation with examples:
1. Creating a Promise: We’ll start by creating a Promise that simulates an asynchronous operation, such as fetching data from an API.

const fetchData = () => {
  return new Promise((resolve, reject) => {
    // Simulating an asynchronous operation (e.g., fetching data from an API)
    setTimeout(() => {
      const data = { id: 1, name: 'John' };
      resolve(data); // Resolve with data
      // reject(new Error('Failed to fetch data')); // Reject with an error
    }, 1000);
  });
};

2. Using Promises in a Functional Component: We’ll create a functional component named MyComponent and use the useState hook to manage the component’s state. We’ll also use the useEffect hook to perform the asynchronous operation when the component mounts.

import React, { useState, useEffect } from 'react';

const MyComponent = () => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetchData()
      .then(data => {
        setData(data);
      })
      .catch(error => {
        setError(error.message);
      });
  }, []); // Empty dependency array to run effect only once

  if (error) {
    return <div>Error: {error}</div>;
  }

  if (!data) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Data:</h1>
      <p>{JSON.stringify(data)}</p>
    </div>
  );
};

export default MyComponent;

In this example:

  • We use the useState hook to create state variables for data and error.
  • We use the useEffect hook to perform the asynchronous operation (calling fetchData()) when the component mounts. We pass an empty dependency array [] to ensure that the effect runs only once after the initial render.
  • Inside the useEffect, we use the Promise’s then() method to handle the resolved data and update the state with setData(). We also use the catch() method to handle any errors and update the state with setError().

3. Rendering the Component: Finally, we render the MyComponent in the root component of our application or wherever it’s needed.

import React from 'react';
import ReactDOM from 'react-dom';
import MyComponent from './MyComponent';

ReactDOM.render(<MyComponent />, document.getElementById('root'));

With this setup, when MyComponent mounts, the useEffect hook triggers the asynchronous operation (fetchData()). Once the Promise resolves, the component’s state is updated with the fetched data using setData(). If there’s an error, it’s caught and handled using setError(). The component renders different UI based on the state (loading, data, or error), providing a smooth user experience.