Skip to content

Instantly share code, notes, and snippets.

@xantiagoma
Created April 4, 2024 02:35
export function asyncComponent<T>(
fn: (props: T) => Promise<JSX.Element>
): React.FC<T> {
return fn as any;
}
import { Suspense } from "react";
import { asyncComponent } from "./async-component";
const GeneratorComponent = asyncComponent(
async (props: {
generator: AsyncGenerator<JSX.Element, JSX.Element, JSX.Element>;
}) => {
const { generator } = props;
let result = await generator.next();
if (result.done) {
return result.value;
}
return (
<Suspense fallback={result.value}>
<GeneratorComponent generator={generator} />
</Suspense>
);
}
);
export function generatorComponent<T>(
fn: (props: T) => AsyncGenerator<JSX.Element, JSX.Element, JSX.Element>
): React.FC<T> {
// eslint-disable-next-line react/display-name
return (props: T) => {
return <GeneratorComponent generator={fn(props)} />;
};
}
import { generatorComponent } from "./generator-component";
export const dynamic = "force-dynamic";
const sleep = (ms: number) => new Promise<void>((res) => setTimeout(res, ms));
const Steps = generatorComponent(async function* () {
let i = 0;
yield <h1>Step {++i}</h1>;
await sleep(2000);
yield <h1>Step {++i}</h1>;
await sleep(2000);
yield <h1>Step {++i}</h1>;
await sleep(2000);
return <h1>Step {++i}</h1>;
});
export default function GeneratorPage() {
return (
<div className="h-screen flex flex-col gap-4 justify-center items-center">
<h1 className="text-xl font-bold">
The contents below are being streamed
</h1>
<div className="bg-gray-800 py-8 w-64 flex justify-center items-center text-xl">
<Steps />
</div>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment