ProNextJS
    Professional Next.js Course
    Loading price
    30-Day Money-Back Guarantee
    lesson

    Granular Suspense in React

    Jack HerringtonJack Herrington

    So we've got our stocks app set up with Suspense, but let's make it more granular. This code can be found in the stocks-with-suspense-granular directory.

    First, we'll remove the fallback from the page.tsx suspense block since we're going to make it more granular:

    // inside of the Home component return:
    <Suspense>
      <Dashboard />
    </Suspense>
    

    Over in dashboard.tsx we'll get rid of the Promise.all and instead fetch each stock individually. To do this, we'll create a StockDisplay component that takes a stockPromise as a prop and uses the use hook to wait for the promise to resolve:

    // inside of app/dashboard.tsx
    
    import { Suspense, use } from "react";
    
    import { getStocks } from "@/lib/getStocks";
    import { StockInfo } from "@/types";
    
    function StockDisplay({ stockPromise }: { stockPromise: Promise<StockInfo> }) {
      const { name, ui } = use(stockPromise);
      return (
        <div>
          <div className="font-bold text-3xl">{name}</div>
          <div>{ui}</div>
        </div>
      );
    }
    

    Next, we'll use the StockDisplay component in the Dashboard component. Surrounding it with a Suspense block will make it more granular:

    // inside of app/dashboard.tsx
    export default async function Dashboard() {
      const stocks = await getStocks();
    
      return (
        <div className="grid grid-cols-3 gap-4 mt-5">
          {stocks.map((stockPromise, index) => (
            <Suspense key={index} fallback={<div>Loading...</div>}>
              <StockDisplay stockPromise={stockPromise} />
            </Suspense>
          ))}
        </div>
      );
    }
    

    Now, each stock will load independently, and we'll see a loading indicator for each stock that hasn't loaded yet. That's much better! We've achieved more granular suspense in our React app!

    loading messages

    In the next lesson, we'll look at how to do this with server actions. That's where it gets really interesting as we start creating our own DIY streaming system from the server. Server actions can return UI, so we can return interactive elements right from the server action.

    Transcript

    All right, so I've copied stocks with suspense to stocks with suspense granular, and now you can see that on its own. Let me go and show you my solution. So first thing we need to do is get rid of the fallback around dashboard. And then we're going to make dashboard more granular, so we're going to bring in suspense here. So one thing I know for sure that we don't want to do is this await of promise all.

    So we just want to get back the list of stocks. So that's currently, if we look at this, that is now an array of promises to stock info. Okay, cool. So we have here now a stock promise. So what are we going to do with that?

    Well, alright. So let's go and take this section and break it out into its own component. So I'm going to create a new Stock Display component. And it's going to take a Stock Promise to a stock info. And then I'm going to bring in use because what use can do is take a promise and wait for it to resolve and then get the data from it.

    So from that I'm going to get the stock. So now from the stock promise I can get the stock and really I can get the name and the UI from that. Okay, this is looking pretty good so far. So how do we use this? We'll go down here and we will use a stock display.

    Now we don't really have a key, so I'm just gonna use the index for the key. And now I've gotta give it that stock promise. All right, let's see how that looks. So I hit refresh. We're still getting a lot of lagging time so that's not good but it's not blowing up so that's good too.

    So What happens if now I wrap that stock display in a suspense? We can get rid of the key here. Hit save. Oh, that's looking so much better. So now I've got a much more granular display and everything works just as you'd expect.

    And I think this might actually be fine for a lot of your given scenarios. I think actually doing refresh here is great. In the next section, I'm gonna show you how to do this with server actions. And that's where it gets really interesting as we start kind of creating our own DIY streaming system from the server using Server Actions. Now just be clear, Server Actions can return UIs.

    So you note that we're doing this UI thing down here. We're returning an interactive element from that function. We can actually do that from server actions. It's really cool. I'll see you in the next video as we work into getting server actions into this model.