Reputation: 21
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