Next.js Discord

Discord Forum

Suspense doesn't work

Unanswered
Arboreal ant posted this in #help-forum
Open in Discord
Arboreal antOP
I have a dashboard page that retrieves users Guilds from the Discord API. The API has a 700ms response time, which is too long to wait for the data before rendering the page. I tried using suspense, but it still waited for the data to arrive before showing the skeleton component. What can I do to show a skeleton component immediately and then replace it with the data once it's fetched?
//page.js
import MyServer from "./myServers";
import { Suspense } from "react";
import Skeleton from "./Skeleton";

export const dynamic = "force-dynamic";

const DashBoard = async () => {
  return (
    <>
      <Suspense fallback={<Skeleton />}>
        <MyServer />
      </Suspense>
    </>
  );
};

export default DashBoard;
// myServer.js
import { getUser } from "@/app/utilities/getUser";
import { cookies } from "next/headers";
import { permanentRedirect } from "next/navigation";
import "./dashboard.css";

export const dynamic = "force-dynamic";

const MyServer = async () => {
  async function getUserGuilds() {
    try {
      const data = await fetch("https://discord.com/api/users/@me/guilds", {
        headers: {
          Authorization: `Bearer ${User.accessToken}`,
        },
        cache: "no-store",
      });
      return data.json();
    } catch (err) {
      return null; 
    }
  }

  

  const cookieStore = cookies();
  const sessionid = cookieStore.get("sessionid");

  const User = await getUser(sessionid);

  if (!User) {
    return permanentRedirect(process.env.NEXT_PUBLIC_OAUTH_URL);
  }

  const servers = await getUserGuilds();

  console.log(servers);

  return (
    <>
      <h1>My Servers</h1>
      <div className="server-container">
        {servers?.map((server) => (
          <div key={server.id} className="server">
            <img
              src={`https://cdn.discordapp.com/icons/${server.id}/${server.icon}`}
              alt=""
            />
            <h2 className="server-name">{server.name}</h2>
          </div>
        ))}
      </div>
    </>
  );
};

export default MyServer;

15 Replies

@Arboreal ant I have a dashboard page that retrieves users Guilds from the Discord API. The API has a 700ms response time, which is too long to wait for the data before rendering the page. I tried using suspense, but it still waited for the data to arrive before showing the skeleton component. What can I do to show a skeleton component immediately and then replace it with the data once it's fetched?js //page.js import MyServer from "./myServers"; import { Suspense } from "react"; import Skeleton from "./Skeleton"; export const dynamic = "force-dynamic"; const DashBoard = async () => { return ( <> <Suspense fallback={<Skeleton />}> <MyServer /> </Suspense> </> ); }; export default DashBoard; js // myServer.js import { getUser } from "@/app/utilities/getUser"; import { cookies } from "next/headers"; import { permanentRedirect } from "next/navigation"; import "./dashboard.css"; export const dynamic = "force-dynamic"; const MyServer = async () => { async function getUserGuilds() { try { const data = await fetch("https://discord.com/api/users/@me/guilds", { headers: { Authorization: `Bearer ${User.accessToken}`, }, cache: "no-store", }); return data.json(); } catch (err) { return null; } } const cookieStore = cookies(); const sessionid = cookieStore.get("sessionid"); const User = await getUser(sessionid); if (!User) { return permanentRedirect(process.env.NEXT_PUBLIC_OAUTH_URL); } const servers = await getUserGuilds(); console.log(servers); return ( <> <h1>My Servers</h1> <div className="server-container"> {servers?.map((server) => ( <div key={server.id} className="server"> <img src={`https://cdn.discordapp.com/icons/${server.id}/${server.icon}`} alt="" /> <h2 className="server-name">{server.name}</h2> </div> ))} </div> </> ); }; export default MyServer;
it seems nextjs partial prerendering (ppr) is for this purpose, so try it out (but it is unstable so expect bugs)
if you cant use ppr, it seems to me you need to use client-side rendering for now
@joulev it seems nextjs partial prerendering (ppr) is for this purpose, so try it out (but it is unstable so expect bugs)
Arboreal antOP
but isnt suspense supposed to just send the fallback component while getting the data and then replace it with the data once it gets it?
@Arboreal ant but isnt suspense supposed to just send the fallback component while getting the data and then replace it with the data once it gets it?
yes but from my observation, it only works reliably for when you navigate between pages. when you load the page, it may work or it may not work and this could be a bug but also [could be a feature](https://discord.com/channels/752553802359505017/752647196419031042/1218069832730279986)
for my app at work, it works and first load does show the skeleton. but i cannot explain why it works and why yours doesn't – i didn't do anything special for it at all
Arboreal antOP
thats weird, i've also searched for other people having this issue and i found nothing, from what i have seen my code should work and show the skeleton on page refresh but i guess i will look into ppr
so how would i do this with Partial Prerendering? keep the suspense or do i need to modify the code
I believe you can just keep the code as-is
Arboreal antOP
welp i added
  experimental: {
    ppr: true,
  },
and installed next canary but nothing changes
Well I haven’t actually used ppr myself so can’t say much. I only know that they are making the ppr thing and that it seems to solve this problem
Arboreal antOP
so i tried doing it in [insomnia](https://insomnia.rest/) and it worked, it first showed the fallback component and then the data, i then tried it again in chrome edge and firefox and nothing, there was no response until it got the data, i am no confused on why this is happening
Arboreal antOP
Bump
@Arboreal ant Bump
please only bump at most once a day. four in 3 hours is too frequent
@joulev please only bump at most once a day. four in 3 hours is too frequent
Arboreal antOP
oh thought you are allowed to do it once every hour
my bad