Skip to content

Commit

Permalink
Add recursive stream render
Browse files Browse the repository at this point in the history
  • Loading branch information
lmatteis committed Aug 8, 2023
1 parent dedcd1a commit 4334f7d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const App = () => {
return (
<div className="App">
<h2>
Infinite scroll React Server Components using{" "}
Infinite scroll streaming chunks of React Server Components using{" "}
<a href="https://waku.gg/">Waku</a>
</h2>
<p>
Expand Down
73 changes: 60 additions & 13 deletions src/components/Chunk.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,67 @@
async function fetchPage(page: number) {
// artificial delay, 3s
await new Promise((resolve) => setTimeout(resolve, 3000));
import { Suspense } from "react";

// Create 5 fake items in a page
const chunkItems = [1, 2, 3, 4, 5].map((i) => i + 5 * (page - 1));
return chunkItems;
function randomIntFromInterval(min: number, max: number) {
// min and max included
return Math.floor(Math.random() * (max - min + 1) + min);
}

export default async function Chunk({ page }: { page: number }) {
const chunkItems = await fetchPage(page);
const timeout = (resolve: any) =>
setTimeout(resolve, randomIntFromInterval(0, 2000));

function createStream(page: number) {
const stream = new ReadableStream({
async start(controller) {
// push 5 items at random intervals
await new Promise(timeout);
controller.enqueue(1 + 5 * (page - 1));

await new Promise(timeout);
controller.enqueue(2 + 5 * (page - 1));

await new Promise(timeout);
controller.enqueue(3 + 5 * (page - 1));

await new Promise(timeout);
controller.enqueue(4 + 5 * (page - 1));

await new Promise(timeout);
controller.enqueue(5 + 5 * (page - 1));
},
pull(controller) {
// We don't really need a pull in this example
},
cancel() {
// This is called if the reader cancels,
// so we should stop generating strings
},
});

return stream;
}

async function Token({ reader }: { reader: ReadableStreamDefaultReader }) {
const { done, value } = await reader.read();

if (done) return null;

return (
<>
<p>Post {value}</p>
<RecursiveReader reader={reader} />
</>
);
}

function RecursiveReader({ reader }: { reader: ReadableStreamDefaultReader }) {
return (
<div key={page}>
{chunkItems.map((item) => (
<p key={item}>Post {item}</p>
))}
</div>
<Suspense fallback="wat">
<Token reader={reader} />
</Suspense>
);
}

export default async function Chunk({ page }: { page: number }) {
const stream = createStream(page);
const reader = stream.getReader();
return <RecursiveReader reader={reader} />;
}

0 comments on commit 4334f7d

Please sign in to comment.