Next.js Discord

Discord Forum

Getting NEXT_REDIRECT error, when trying to redirect Server Actions in Next.js 13.

Answered
Satin Angora posted this in #help-forum
Open in Discord
Avatar
Satin AngoraOP
Hi, we are currently implementing authentication for our client, and have a blocking issue which for some reason exists in Next.js 13. In some cases the redirect() function from next/redirect works properly. For example, one instance where it works properly is a nested layout.tsx file. Here are the contents:
export default async function Layout({ children }: LayoutProps) {
  if (!cookies().get("jwt")) redirect("/b");

  return (
    <></>
  );
}


Suppose the route of this layout is /a.

Now, whenever I try to redirect from Server Actions from route /c to /a/b, it throws the error attached to this thread as an image. It also failes to redirect to /a or / directly for some reason.
Image
Answered by fuma ๐Ÿ’™ joulev
You have to use client-side redirect instead:
import { useRouter } from "next/navigation";

const router = useRouter();
router.push("/b");
View full answer

8 Replies

Avatar
Satin AngoraOP
Here's the code where it's implemented:

"use client";

import Image from "next/image";
import { useEffect, useRef } from "react";
import GenericButton from "../../components/GenericButton";
import axios from "axios";
import { onboard } from "./_actions";

import favicon from "../favicon.ico";

export default function Page() {
  const googleOAuthButtonRef = useRef<HTMLButtonElement | null>(null);

  useEffect(() => {
    window.google.accounts.id.initialize({
      itp_support: true,
      callback: async ({ credential }) => {
        const response = await axios.post("/api/v1/onboard", {
          strategy: "google",
          credential,
        });
        console.log({ credential, response });
        if (response.status === 200) await onboard(response.data.token);
      },
      client_id: process.env.NEXT_PUBLIC_GOOGLE_OAUTH_CLIENT_ID!,
    });
    window.google.accounts.id.disableAutoSelect();
    window.google.accounts.id.renderButton(googleOAuthButtonRef.current!, {
      type: "standard",
      size: "medium",
      text: "continue_with",
      theme: "outline",
      shape: "pill",
      locale: "en-US",
      logo_alignment: "left",
    });

    window.google.accounts.id.prompt();
  }, []);

  return (
    <div className="w-full h-screen flex items-center justify-center">
        <div className="w-full flex gap-8">
          <div className="flex items-center flex-col gap-2">
            <GenericButton className="w-full">
              Continue with Email
            </GenericButton>
            <button ref={googleOAuthButtonRef}></button>
          </div>
        </div>
    </div>
  );
}
And here's the code for the server action:
"use server";

import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { add, getMilliseconds } from "date-fns";

export async function onboard(token: string) {
  cookies().set({
    path: "/",
    name: "jwt",
    value: token,
    // The internal state cookie will expire in 1.5 months, and the user will need to
    // login again to access the platform.
    expires: getMilliseconds(add(new Date(), { months: 1, days: 15 })),
  });

  redirect("/dashboard/control");
}
Avatar
fuma ๐Ÿ’™ joulev
You have to use client-side redirect instead:
import { useRouter } from "next/navigation";

const router = useRouter();
router.push("/b");
Answer
Avatar
fuma ๐Ÿ’™ joulev
As I remember, redirect in server actions only works when you're firing it from forms
Avatar
Satin AngoraOP
Oh, interesting. Thank you. Cookies should work fine right?
Avatar
fuma ๐Ÿ’™ joulev
yes, cookies always work in server actions
Avatar
Satin AngoraOP
Ok, thank you.
Avatar
Tufted Flycatcher
thank you @fuma ๐Ÿ’™ joulev