There are many tools available for communicating between the client and server in a Next.js application. One of these tools is Suspense, which can be used to handle asynchronous operations like data fetching.
In this section, we'll learn about Suspense by working with an interactive stock ticker app:
Currently, the app has a long loading time due to artificial delays in the data fetching process. We'll explore how to use Suspense to improve the user experience by providing feedback during the loading process.
Starting Code Overview
Let's break down the existing code for our stock ticker app and identify the bottlenecks. This can be found in the 05-suspense-and-diy-streaming
directory of the course repository.
The main component is a dashboard displaying a list of stocks. This dashboard currently fetches stock data using a getStocks
function.
// src/app/dashboard.tsx
import { getStocks } from "@/lib/getStocks";
export default async function Dashboard() {
const stocks = await Promise.all(await getStocks());
return (
<div className="grid grid-cols-3 gap-4 mt-5">
{stocks.map(({ name, ui }) => (
<div key={name}>
<div className="font-bold text-3xl">{name}</div>
<div>{ui}</div>
</div>
))}
</div>
);
}
The getStocks
function generates fake stock data with artificial delays to simulate network requests, and each of the promises resolves to a stock object that includes a component:
// inside lib/getStocks.tsx
"use server";
import type { StockInfo } from "@/types";
import StockWithCounter from "@/components/stock-with-counter";
const STOCKS = ["ARPL", "GLOG", "MDFT", "AMZO", "FBL", "TSLR"];
async function generateFakeStock(
name: string,
delay: number
): Promise<StockInfo> {
// Simulate a delay of at least 1 second
await new Promise((resolve) =>
setTimeout(resolve, Math.random() * delay + 1000)
);
const price = Math.random() * 1000 + 100;
return {
name,
price,
ui: <StockWithCounter name={name} price={price} />,
};
}
export const getStocks = () => {
return STOCKS.map((id) => generateFakeStock(id, 3000));
};
Right now, the Dashboard
component waits for all promises to resolve before rendering. This leads to a noticeable delay, especially with the artificial lag we've introduced.
The Solution: Suspense
So how do we make this better for the user? The answer is Suspense!
Suspense is a mechanism in React for handling asynchronous operations like data fetching. Instead of blocking the entire page while waiting for data, we can use Suspense to display a fallback UI. This fallback could be a loading indicator, a placeholder, or even some initial content, improving the perceived performance and making the app feel more responsive.
Your challenge is to use Suspense to enhance the user experience by providing feedback during the data loading process. We'll go over the solution in the next video. Good luck!