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
You have to use client-side redirect instead:
import { useRouter } from "next/navigation";

const router = useRouter();
router.push("/b");
Answer
Avatar
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
yes, cookies always work in server actions
Avatar
Satin AngoraOP
Ok, thank you.
Avatar
Tufted Flycatcher
thank you @fuma ๐Ÿ’™ joulev