Skip to content

Instantly share code, notes, and snippets.

@borispoehland
Created January 13, 2024 08:26
Show Gist options
  • Save borispoehland/212ee00972e86a5c912bb31ab4d08efd to your computer and use it in GitHub Desktop.
Save borispoehland/212ee00972e86a5c912bb31ab4d08efd to your computer and use it in GitHub Desktop.
Next.js 14 + React RSC Signout flow using efficient data fetching with <Await />
import { Thenable } from "react";
export async function Await<T>({
promise,
children,
}: {
promise: Thenable<T>;
children: (value: T) => JSX.Element;
}) {
const data = await promise;
return children(data);
}
import { Await } from "@/components/Await"
import { auth } from "@/modules/auth/auth"
import { Suspense } from "react"
import { SignOut } from "./SignOut"
export function Navbar() {
return (
<nav>
<div>...</div>
<ul>...</ul>
<Suspense fallback="Auth streaming in...">
<Await promise={auth()}>{(auth) => <SignOut auth={auth} />}</Await>
</Suspense>
</nav>
)
}
"use client";
import { SubmitButton } from "@/components/SubmitButton";
import { Session } from "next-auth";
import { signOut } from "next-auth/react";
import { useRouter } from "next/navigation";
export function SignOut({ auth }: { auth: Session | null }) {
const router = useRouter();
if (!auth) {
// or sign in button
return <></>;
}
return (
<form
action={async () => {
await signOut({ redirect: false });
router.refresh();
}}
>
<SubmitButton>Sign out</SubmitButton>
</form>
);
}
"use client";
import { ComponentProps } from "react";
import { Button } from "./ui/button";
import { useFormStatus } from "react-dom";
export function SubmitButton({
disabled,
...props
}: ComponentProps<typeof Button>) {
const status = useFormStatus();
return (
<Button type="submit" disabled={disabled || status.pending} {...props} />
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment