I want to do a server side request and fetch user data, which is authenticated via cookie. I forward the cookies via the cookies
function (not shown in example).
When the authentification fails and I get a 401 back, I want to do a redirect to /login?redirect=[page where the request failed]
My /app/profile/page.tsx
:
import { RedirectType, redirect } from "next/navigation";
const MyProfile = async () => {
const profile = await fetch("https://example.com/api/user/profile"); // authentificated via cookie
if (profile.status === 401) {
// "/profile" is hardcoded here, but it should be the current path
redirect("/login?redirect=/profile", RedirectType.replace);
}
if (!profile) return <div>Loading...</div>;
const profileData = await profile.json();
return <div>My name is {profileData.name}</div>;
};
export default MyProfile;
I need to do authenticated requests on nearly every page - is there a way not to hardcode the redirect param on the server side? Do I have another conceptual error?
Thanks!
You can return a client component in your if statement that does the redirect automatically for you by uisng the usePathname
function, without you needing to hardcode the redirect param every time.
You can call the client component RedirectComponent.tsx, and this is how it is going to probably look like:
'use client'
import { usePathname, redirect, RedirectType } from 'next/navigation'
export function RedirectComponent() {
const pathname = usePathname()
redirect("/login?redirect=" + pathname, RedirectType.replace);
return <></>
}
This client component does not return any jsx, or you can modify it to return any jsx you want, but as soon as you call or return this client component in your server component, the usePathname
will read the current URL's pathname and append it to the url you want to redirect to, in this case login?redirect
+ the current url pathname.
And in your code you can do something like this to call it:
import { RedirectType, redirect } from "next/navigation";
import {RedirectComponent} from "./RedirectComponent"
const MyProfile = async () => {
const profile = await fetch("https://example.com/api/user/profile"); // authentificated via cookie
if (profile.status === 401) {
// return the RedirectComponent here to automatically redirect you to the desired page
return <RedirectComponent />
}
if (!profile) return <div>Loading...</div>;
const profileData = await profile.json();
return <div>My name is {profileData.name}</div>;
};
export default MyProfile;
Here is an answer from the nextjs docs:
usePathname
intentionally requires using a Client Component. It's important to note Client Components are not a de-optimization. They are an integral part of the Server Components architecture.