Correct way of consuming TRPC NextAuth context with 'use client' useRouter
Answered
Prairie yellowjacket posted this in #help-forum
Prairie yellowjacketOP
Hi, I have made a header component /_comp.../Header.tsx that has pathname route logic this requires 'use client' however, I have a sign in function that consume the TRPC context via next auth getServerAuthSession(), due to the 'use client' we now get.
Error: ⌠Attempted to access a server-side environment variable on the client
partly due to the prisma server tring to validate the user logic
what's the best way around this, client/server logic?
Error: ⌠Attempted to access a server-side environment variable on the client
partly due to the prisma server tring to validate the user logic
what's the best way around this, client/server logic?
Answered by Ray
1. you should use metadata api for the header in app router instead of
2 we can render the server component with the children props in client component
next/head
2 we can render the server component with the children props in client component
20 Replies
Ray
turn the sign in function to server action so we can handle it on server side
Prairie yellowjacketOP
so break out the header function ?
header.tsx
'use client'
import signinhelper.tsx
-consume rout logic
-consume signinhelper
signinhelper.tsx
'use server'
-consume getServerAuthSession()
Ray
header.tsx
'use client'
import signinhelper.tsx
-consume rout logic
-consume signinhelper
signinhelper.tsx
'use server'
-consume signin()
Prairie yellowjacketOP
hmm, a bug? so we have some psuedo 'use client' ('use server' (async getServerAuthSession())
1 of 1 unhandled error
Next.js is up to date
Unhandled Runtime Error
Error: async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server.
Ray
could you show the code
Prairie yellowjacketOP
sure
src/app/page.tsx
import type { NextPage } from "next";
import Head from "next/head";
import { unstable_noStore as noStore } from "next/cache";
import Header from "./_components/Header";
const Home: NextPage = async () => {
noStore();
return (
<>
<Head>
<title>Create T3 App</title>
<meta name="description" content="Generated by create-t3-app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className="flex min-h-screen flex-col text-black">
<Header />
</div>
</>
);
};
export default Home;
_components/Header.tsx
'use client'
import React from "react";
import Link from "next/link";
import { usePathname } from 'next/navigation'
import SignInHelper from "./signinhelper";
const links = [
{ href: "/jobs", label: "Job Seekers" },
{ href: "/jobs/create", label: "Post a Job" },
{ href: "#", label: "About Us" },
{ href: "#", label: "Contact" },
{ href: "conference", label: "Conferences" },
];
export default function Header() {
const pathname = usePathname()
return (
<header className="mx-4 flex h-16 items-center bg-[#ffffff] px-4 md:mx-8 lg:mx-16 lg:px-6">
<Link className="flex items-center justify-center" href="/">
<span className="ml-2 text-lg font-bold">MatchPoint</span>
</Link>
<nav className="ml-auto flex items-center gap-4 sm:gap-6">
{links.map((link, index) => (
<Link
key={index}
className={`text-sm font-medium underline-offset-4 hover:underline ${pathname === link.href ? "text-gray-500" : ""}`}
href={link.href}
>
{link.label}
</Link>
))}
<SignInHelper />
</nav>
</header>
);
};
src/app/_components/signinhelper.tsx
'use server'
import React from "react";
import Link from "next/link";
import { getServerAuthSession } from "~/server/auth";
export default async function SignInHelper() {
const session = await getServerAuthSession();
return (
<>
<Link href={session ? "/api/auth/signout" : "/api/auth/signin"}>
<div className="rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20">
{session ? "Sign out" : "Sign in"}
</div>
</Link>
</>
);
}
Ray
ok a few problem here
import {type Metadata} from 'next'
import { unstable_noStore as noStore } from "next/cache";
import Header from "./_components/Header";
export const metadata: Metadata = {
title: 'Create T3 App',
description: 'Generated by create-t3-app'
}
const Home = async () => {
noStore();
return (
<>
<div className="flex min-h-screen flex-col text-black">
<Header>
<SignInHelper />
</Header>
</div>
</>
);
};
export default Home;
'use client'
import React from "react";
import Link from "next/link";
import { usePathname } from 'next/navigation'
const links = [
{ href: "/jobs", label: "Job Seekers" },
{ href: "/jobs/create", label: "Post a Job" },
{ href: "#", label: "About Us" },
{ href: "#", label: "Contact" },
{ href: "conference", label: "Conferences" },
];
export default function Header({children}) {
const pathname = usePathname()
return (
<header className="mx-4 flex h-16 items-center bg-[#ffffff] px-4 md:mx-8 lg:mx-16 lg:px-6">
<Link className="flex items-center justify-center" href="/">
<span className="ml-2 text-lg font-bold">MatchPoint</span>
</Link>
<nav className="ml-auto flex items-center gap-4 sm:gap-6">
{links.map((link, index) => (
<Link
key={index}
className={`text-sm font-medium underline-offset-4 hover:underline ${pathname === link.href ? "text-gray-500" : ""}`}
href={link.href}
>
{link.label}
</Link>
))}
{children}
</nav>
</header>
);
};
import Link from "next/link";
import { getServerAuthSession } from "~/server/auth";
export default async function SignInHelper() {
const session = await getServerAuthSession();
return (
<>
<Link href={session ? "/api/auth/signout" : "/api/auth/signin"}>
<div className="rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20">
{session ? "Sign out" : "Sign in"}
</div>
</Link>
</>
);
}
Ray
1. you should use metadata api for the header in app router instead of
2 we can render the server component with the children props in client component
next/head
2 we can render the server component with the children props in client component
Answer
Prairie yellowjacketOP
ok so you have brought the signinhelper 'use server' above the 'use client' and set it as a child. will give this a go
Ray
you don't need server action in this case, I thought you had a sign in function for it
Prairie yellowjacketOP
yes, this has worked. (I had to drop some of the default s for the functions as it was giving some undefined erorr)
for others that tread this path
see working example here
https://github.com/SkippyHub/nextauth-nextrouting-client-server
for others that tread this path
see working example here
https://github.com/SkippyHub/nextauth-nextrouting-client-server
Thanks Ray.
we might have found a bug about using the server actions.
as in psuedo 'use client' ('use server' (async server action())
we might have found a bug about using the server actions.
as in psuedo 'use client' ('use server' (async server action())
Ray
no it is not bug, we can't turn a client component to server component with
'use server'
Prairie yellowjacketOP
okay, thanks for help and clearign that up
Ray
your welcome