a78d43a0cd7059a7a66b
·2 min read

Streaming in React with Suspense: A Seamless User Experience

react
suspense
lazy-loading
error-boundary
4d5fd787ac74e0caa4f7

Sohan R. Emon

Developer, Learner, Tech Enthusiast

React has features like Suspense to make streaming data and content loading smoother than ever.

Streaming data in React with Suspense is a game-changer. It allows us to progressively load data and render content as it becomes available, reducing the initial load time of our applications. In this article, we'll explore how to implement streaming in React using Suspense.

Streaming a List of Items

Let's start with a simple example where we load a list of items from an API and render them progressively as they arrive. We'll use the React.Suspense component to wrap our asynchronous data fetching.

jsx
import React, { Suspense } from 'react';

const fetchItems = () => {
  // Simulate an API call with setTimeout
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(['Item 1', 'Item 2', 'Item 3']);
    }, 2000);
  });
};

const ItemList = () => {
  const items = fetchItems();

  return (
    <div>
      <h1>Streaming Items</h1>
      <Suspense fallback={<div>Loading...</div>}>
        {items.map((item, index) => (
          <Item key={index} item={item} />
        ))}
      </Suspense>
    </div>
  );
};

const Item = ({ item }) => {
  return <div>{item}</div>;
};

export default ItemList;

In the above code:

  • We define a function fetchItems that simulates an API call, returning a promise after 2 seconds.
  • Inside the ItemList component, we use React.Suspense to specify a fallback UI while the data is loading.
  • We map over the items and render them as they arrive.

With this setup, the items will render progressively as they are fetched, providing a smoother user experience.

Handling Errors

Streaming data can also handle errors gracefully. If an error occurs during data fetching, we can use the React.ErrorBoundary to capture and display the error to the user.

jsx
import React, { Suspense } from 'react';

// ...fetchItems function

const ErrorBoundary = (props) => {
  return (
    <React.ErrorBoundary
      fallback={(error) => (
        <div>
          <h2>Error: {error.message}</h2>
        </div>
      )}
    >
      {props.children}
    </React.ErrorBoundary>
  );
};

const ItemList = () => {
  return (
    <div>
      <h1>Streaming Items</h1>
      <ErrorBoundary>
        <Suspense fallback={<div>Loading...</div>}>
          {fetchItems().map((item, index) => (
            <Item key={index} item={item} />
          )}
        </Suspense>
      </ErrorBoundary>
    </div>
  );
};

// ...Item component

export default ItemList;

Here, we wrap our rendering components in an ErrorBoundary component, which will capture and display any errors that occur during the streaming process.

Conclusion

With the examples provided, you can start implementing streaming in your React applications today.

Found this useful?