Skip to content

Instantly share code, notes, and snippets.

@rphlmr
Created August 21, 2023 08:19
Show Gist options
  • Save rphlmr/3cf3acea17bf4ed263aa5612a4208f79 to your computer and use it in GitHub Desktop.
Save rphlmr/3cf3acea17bf4ed263aa5612a4208f79 to your computer and use it in GitHub Desktop.
Next13 paginate stream
import { faker } from "@faker-js/faker";
import { Suspense, cache } from "react";
import Link from "next/link";
export const dynamic = "force-dynamic";
export const revalidate = 0;
const salesFromDB = Array.from(
{ length: 21 },
() =>
({
id: faker.string.nanoid(),
product: faker.commerce.productName(),
email: faker.internet.email({ provider: "gmail" }),
}) as const,
);
const getSales = cache(async (pageParam: number = 1) => {
// await new Promise((resolve) => setTimeout(resolve, Math.random() * 1000));
const page = pageParam < 1 ? 1 : pageParam;
const offset = (page - 1) * 10;
const sales = salesFromDB.slice(offset, offset + 11); // 10 + 1 for hasNext
return { results: sales.slice(0, 10), hasNext: sales.length === 11 };
});
export default async function Page({
searchParams,
}: {
searchParams: { page: number };
}) {
const page = searchParams.page || 1;
return (
<div
style={{
width: "80vw",
margin: "0 auto",
}}
>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<h1>Sales</h1>
<table>
<thead>
<tr>
<th>Command ID</th>
<th>Product Name</th>
<th>Customer Email</th>
</tr>
</thead>
<Suspense
key={page}
fallback={
<tbody>
<tr>
<td>Loading...</td>
</tr>
</tbody>
}
>
<SalesTable page={page} />
</Suspense>
</table>
<div
style={{
display: "flex",
gap: "1rem",
}}
>
{page > 1 && (
<Link
href={`/paginate?page=${
Number(page) - 1
}&ck=${Math.round(Math.random() * 1000)}`}
>
Prev
</Link>
)}
<Suspense key={page}>
<NextButton page={page} />
</Suspense>
</div>
</div>
</div>
);
}
async function SalesTable({ page }: { page: number }) {
const sales = await getSales(page);
return (
<tbody>
{sales.results.map((sale) => (
<tr key={sale.id}>
<td>{sale.id}</td>
<td>{sale.product}</td>
<td>{sale.email}</td>
</tr>
))}
</tbody>
);
}
async function NextButton({ page }: { page: number }) {
const sales = await getSales(page);
return (
sales.hasNext && (
<Link
href={`/paginate?page=${Number(page) + 1}&ck=${Math.round(
Math.random() * 1000,
)}`}
>
Next
</Link>
)
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment