Next.js中使用Server Action调用API失败问题求助
Next.js登录页Server Action调用API问题排查与修复
问题1:Server Action传递报错
原因
Login组件中定义的callAPI是客户端异步函数,将其作为form的action属性传递时,违反了Next.js规则:客户端组件不能直接传递未标记为use server的函数给表单action。即便signInUser标记了use server,但包裹它的callAPI是客户端函数,依然会触发报错。
修改方案
直接将signInUser作为表单的action,并修改signInUser以接收表单提交的FormData:
- 更新
action.ts,让signInUser处理FormData:
"use server"; import { callSignInUser } from "@/lib/server"; export async function signInUser(formData: FormData) { const email = formData.get("email") as string; const password = formData.get("password") as string; if (!email || !password) { return returnError(new Error("邮箱或密码不能为空")); } const res = await callSignInUser(email, password); return res; }
- 修改Login组件,移除
callAPI,直接绑定signInUser到表单action,并给输入框添加name属性:
import Image from "next/image"; import React from "react"; import lady from "../../../public/landing-girl.svg"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import Link from "next/link"; import { signInUser } from "../actions/action"; export default function Login() { return ( <div className="flex flex-1 flex-col justify-center items-center"> <Image src={lady} alt="lady" fill={true} placeholder="empty" priority={false} style={{ objectFit: "cover" }} /> <div className="w-screen h-screen bg-black/20 z-10" /> <div className="w-fit min-w-[500px] h-auto bg-[#F2F2F2]/95 z-20 absolute rounded-lg items-center flex flex-1 px-10 py-5 flex-col"> <span className="text-primary text-3xl font-semibold">Login</span> <span className="text-text-primary mt-3"> Welcome back! Please enter your details. </span> <form action={signInUser} className="mt-5 w-full"> <Input label="Email Id" placeholder="Enter your email" name="email"></Input> <Input label="Password" placeholder="Enter your password" name="password"></Input> <Button className="w-full" type="submit"> Sign In </Button> </form> <span className="mt-5 text-text-primary text-sm"> {"Don't have account? "} <Link href="/signup"> <span className="text-primary font-semibold">Sign Up</span> </Link> </span> </div> </div> ); }
问题2:网络请求指向localhost而非配置地址
原因
- 问题1未解决时,表单执行默认提交行为,直接POST到当前域名(localhost:3000),而非调用Server Action。
fetch请求缺少Content-Type头,服务器无法正确解析JSON请求体;同时API地址拼接时可能出现双斜杠,导致请求地址错误。
修改方案
- 确保问题1已修复,Server Action正常执行(此时API请求在服务器端发起,浏览器网络面板不会显示该请求,只会看到Next.js的Server Action请求)。
- 更新
server.ts,添加请求头并修正地址拼接:
import { isOKResponse, returnError, returnSuccess } from "@/types"; import { createAPIEndpoint } from "."; export const callSignInUser = async (email: string, password: string) => { const json = { email: email, password: password, }; const response = await fetch(createAPIEndpoint("v1/auth/jwt/create/"), { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(json), }); try { const data = await response.json(); if (isOKResponse(response)) { return returnSuccess<{}>(data); } } catch (err) { console.error("登录API请求失败:", err); } return returnError(new Error("登录失败,请稍后重试")); };
- 更新
index.ts的地址拼接逻辑,避免双斜杠:
export const API_BASE_URL = "http://xxxxxx/api/"; export const createAPIEndpoint = (path: string) => { const cleanPath = path.startsWith("/") ? path.slice(1) : path; return `${API_BASE_URL}${cleanPath}`; };
内容的提问来源于stack exchange,提问作者Anuj
相关产品推荐
相关产品推荐

