Gabriel Logan
Gabriel Logan

Reputation: 21

failed to forward action response TypeError: fetch failed - Nextjs 14 - App directory

I'm having an error when using a server action with useEffect and having a redirect to do, I'll show the codes below:

ERROR:

 GET /api/auth/session 200 in 49ms
failed to forward action response TypeError: fetch failed
    at node:internal/deps/undici/undici:13185:13
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

  [cause]: Error
      at makeNetworkError (node:internal/deps/undici/undici:8968:35)
      at httpRedirectFetch (node:internal/deps/undici/undici:10515:32)
      at httpFetch (node:internal/deps/undici/undici:10475:28)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async node:internal/deps/undici/undici:10212:20
      at async mainFetch (node:internal/deps/undici/undici:10202:20)
}
 POST / 200 in 172ms
 GET /users?_rsc=1nj8j 200 in 134ms

my action:

"use server";

import { signIn, signOut } from "@/auth";
import { decrypt } from "@/lib/crypto";

export async function handleLogoutServer() {
  await signOut({
    redirectTo: "/",
  });
}

export async function handleLoginOAuthServer(payload: string) {
  try {
    const parsedPayload = JSON.parse(payload);

    const algorithm = process.env
      .QUERYPARAMS_OAUTH_ALGORITHM as Algorithm["name"];
    const secretKey = process.env.QUERYPARAMS_OAUTH_PRIVATE_KEY as string;

    // decript payload
    if (parsedPayload) {
      const decryptedPayload = decrypt(parsedPayload, algorithm, secretKey);

      const parsedDecryptedPayload = JSON.parse(decryptedPayload);

      const accessToken = parsedDecryptedPayload.accessToken;
      const username = parsedDecryptedPayload.username;
      const email = parsedDecryptedPayload.email;
      const userId = parsedDecryptedPayload.userId;
      const fromServer = parsedDecryptedPayload.fromServer;

      if (fromServer) {
        await signIn("Github", {
          accessToken,
          username,
          email,
          userId,
          redirect: false,
        });

        return true;
      }

      return false;
    }

    return false;
  } catch (error) {
    // eslint-disable-next-line no-console
    console.error("Failed to login", error);
    return false;
  }
}

My client component

"use client";

import { motion } from "framer-motion";
import { useRouter, useSearchParams } from "next/navigation";
import type { TransitionStartFunction } from "react";
import { useCallback, useEffect } from "react";
import { FaGithub } from "react-icons/fa";
import { toast } from "react-toastify";

import { handleLoginOAuthServer } from "@/actions";

interface BtnLoginGithubProps {
  startTransition: TransitionStartFunction;
  isPending: boolean;
}

const serverUrl = process.env.NEXT_PUBLIC_API_BASE_HOST;

export default function BtnLoginGithub({
  startTransition,
  isPending,
}: Readonly<BtnLoginGithubProps>) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const payload = searchParams.get("payload");

  const handleLoginGithub = useCallback(
    async (payload: string) => {
      try {
        const response = await handleLoginOAuthServer(payload);

        if (response) {
          toast.success("Logged in successfully");

          router.replace("/users");
          router.refresh();
        } else {
          router.replace("/login");
        }
      } catch {
        // eslint-disable-next-line no-console
        console.error("Failed to login");
      }
    },
    [router],
  );

  useEffect(() => {
    if (payload) {
      startTransition(async () => {
        await handleLoginGithub(payload);
      });
    }
  }, [handleLoginGithub, payload, startTransition]);

  return (
    <motion.button
      whileHover={{ scale: 1.05 }}
      whileTap={{ scale: 0.95 }}
      disabled={isPending}
      type="button"
      className="flex w-full items-center justify-center gap-2 rounded-md border border-transparent bg-gray-800 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-800 focus:ring-offset-2"
      onClick={() => {
        router.push(`${serverUrl}/auth/github`);
      }}
    >
      <FaGithub />
      Sign in with GitHub
    </motion.button>
  );
}

And by the way, this problem only occurs in dev mode, in production the action does not trigger undefined unintentionally. I wanted some light on this, am I doing something wrong?

Well, I expected it to only give an error if there really was an error, I believe the problem is in the strict mode rendering, BUT I don't know how to fix this.

Upvotes: 0

Views: 203

Answers (0)

Related Questions