尝试将数据提交到我的 Supabase 数据库时,我在开发人员控制台中收到 POST http://localhost:3000/api/user-profile net::ERR_ABORTED 500(内部服务器错误) 错误消息。终端显示 TypeError: res.status is not a function at POST。这是我第一次尝试在 NextJS 中创建 API 路由,所以放轻松。
文件夹结构:
project-root/
│
├── app/
│ ├── api/
│ │ └── user-profile/
│ │ └── route.ts
│ │
│ ├── user-profile/
│ │ └── page.tsx
│ ├── types/
│ │ └── userProfile.ts
│ ├── utils/
│ │ └── client.ts
│ │
│ ├── globals.css
│ └── page.tsx
│
├── public/
│
├── package.json
├── tsconfig.json
/app/api/user-profile/route.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { supabase } from '@/app/utils/client';
import { UserProfileUpdateData } from '@/app/types/userProfile';
// Named export function specifically for handling POST requests
export async function POST(req: NextApiRequest, res: NextApiResponse) {
const {
authUserId,
name,
email,
age,
gender,
occupation,
hourly_rate,
}: UserProfileUpdateData = req.body;
const { data: updateData, error: updateError } = await supabase
.from('users')
.update({ name, email, age, gender, occupation, hourly_rate })
.eq('auth_user_id', authUserId);
if (updateError) {
return res.status(500).json({ error: updateError.message });
}
if (!updateData || (updateData as any[]).length === 0) {
const { error: insertError } = await supabase.from('users').insert([
{
auth_user_id: authUserId,
name,
email,
age,
gender,
occupation,
hourly_rate,
number_of_active_projects: 0,
number_of_completed_projects: 0,
},
]);
if (insertError) {
return res.status(500).json({ error: insertError.message });
}
}
return res
.status(200)
.json({ message: 'User profile updated successfully' });
}
/app/(页面)/用户配置文件/page.tsx
'use client';
import React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import toast from 'react-hot-toast';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import DeveloperButtons from '@/app/components/DeveloperButtons';
const profileSchema = z.object({
name: z.string().min(1, { message: 'Name is required' }),
email: z.string().email({ message: 'Invalid email format' }),
age: z.coerce
.number()
.int()
.min(0, { message: 'Invalid age' })
.max(100, { message: 'Invalid age' }),
gender: z.string().min(1, { message: 'Gender is required' }),
occupation: z.string(),
hourly_rate: z.coerce
.number()
.int()
.min(0, { message: 'Invalid hourly rate' }),
});
type ProfileFormData = z.infer<typeof profileSchema>;
const UserProfile = () => {
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm<ProfileFormData>({
resolver: zodResolver(profileSchema),
});
const onSubmit: SubmitHandler<ProfileFormData> = async (data) => {
const response = await fetch('/api/user-profile/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (response.ok) {
toast.success('Profile updated successfully!');
} else {
toast.error('An error occurred while updating the profile.');
}
};
return (
<div className='container mx-auto p-4'>
<DeveloperButtons />
<form
onSubmit={handleSubmit(onSubmit)}
className='form-control w-full max-w-xs pt-8'
>
<label className='label'>
<span className='label-text'>Name</span>
</label>
<input
type='text'
{...register('name')}
className='input input-bordered w-full max-w-xs'
/>
{errors.name && (
<p className='text-red-500'>{errors.name.message}</p>
)}
<label className='label'>
<span className='label-text'>Email</span>
</label>
<input
type='email'
{...register('email')}
className='input input-bordered w-full max-w-xs'
/>
{errors.email && (
<p className='text-red-500'>{errors.email.message}</p>
)}
<label className='label'>
<span className='label-text'>Age</span>
</label>
<input
type='number'
{...register('age')}
className='input input-bordered w-full max-w-xs'
/>
{errors.age && (
<p className='text-red-500'>{errors.age.message}</p>
)}
<label className='label'>
<span className='label-text'>Gender</span>
</label>
<input
type='text'
{...register('gender')}
className='input input-bordered w-full max-w-xs'
/>
{errors.gender && (
<p className='text-red-500'>{errors.gender.message}</p>
)}
<label className='label'>
<span className='label-text'>Occupation</span>
</label>
<input
type='text'
{...register('occupation')}
className='input input-bordered w-full max-w-xs'
/>
{errors.occupation && (
<p className='text-red-500'>{errors.occupation?.message}</p>
)}
<label className='label'>
<span className='label-text'>Hourly Rate</span>
</label>
<input
type='number'
step='0.01'
{...register('hourly_rate')}
className='input input-bordered w-full max-w-xs'
/>
{errors.hourly_rate && (
<p className='text-red-500'>{errors.hourly_rate.message}</p>
)}
<div className='flex space-x-2 justify-center my-4'>
<button
type='submit'
className='btn btn-primary'
>
Submit
</button>
<button
type='button'
onClick={() => reset()}
className='btn btn-secondary'
>
Reset
</button>
</div>
</form>
</div>
);
};
export default UserProfile;
我的 Supabase 架构上的“用户”表:
user_id(主键,不可为空,int4),姓名(可为空 varchar),电子邮件(不可为空,唯一,varchar),年龄(可为空,int4),性别(可为空 varchar),职业(可为空 varchar),organization_id (可为空 int4)、hourly_rate (可为空 int4)、number_of_active_projects (可为空 int4)、number_of_completed_projects (可为空 int4)、auth_user_id (可为空 uuid)。
在输入逗号时有点懒,但你明白了。
我希望将数据输入到数据库中,但遇到了 500(内部服务器错误)问题。我怀疑它必须处理 onSubmit 的 body: JSON.stringify(data) 方面,但我对 api 很陌生,所以我可能完全错了。
更新:
Ahmed 建议使用 Next/Response。这是更新后的route.ts:(我注释掉了旧的返回值)
import type { NextApiRequest, NextApiResponse } from 'next';
import { supabase } from '@/app/utils/client';
import { UserProfileUpdateData } from '@/app/types/userProfile';
import { NextResponse } from 'next/server';
// Named export function specifically for handling POST requests
export async function POST(req: NextApiRequest /*, res: NextApiResponse */) {
const {
authUserId,
name,
email,
age,
gender,
occupation,
hourly_rate,
}: UserProfileUpdateData = req.body;
const { data: updateData, error: updateError } = await supabase
.from('users')
.update({ name, email, age, gender, occupation, hourly_rate })
.eq('auth_user_id', authUserId);
if (updateError) {
return NextResponse.json(
{ error: updateError.message },
{ status: 500 }
);
// return res.status(500).json({ error: updateError.message });
}
if (!updateData || (updateData as any[]).length === 0) {
const { error: insertError } = await supabase.from('users').insert([
{
auth_user_id: authUserId,
name,
email,
age,
gender,
occupation,
hourly_rate,
number_of_active_projects: 0,
number_of_completed_projects: 0,
},
]);
if (insertError) {
return NextResponse.json(
{ error: insertError.message },
{ status: 500 }
);
// return res.status(500).json({ error: insertError.message });
}
}
return NextResponse.json({ message: 'success' }, { status: 201 });
// return res
// .status(200)
// .json({ message: 'User profile updated successfully' });
}
在终端中,当我点击提交按钮时,它说它正确编译了 /api/user-profile 。在开发人员控制台中,它仍然显示 POST http://localhost:3000/api/user-profile 500(内部服务器错误)。
App Router 中的路由处理程序有一些更新:
NextRequest
而不是 NextApiRequest
。import { NextRequest } from "next/server";
export async function POST(req: NextRequest) {}
request.json()
而不是 request.body
: const {
authUserId,
name,
email,
age,
gender,
occupation,
hourly_rate,
}: UserProfileUpdateData = await req.json();
Response
:return new Response("message", {status: 200})
return new NextResponse("message", {status: 200})
return Response.json({...}, {status: 200})
return NextResponse.json({...}, {status: 200})
这应该有效:
import { NextResponse, type NextRequest } from "next/server";
// Named export function specifically for handling POST requests
export async function POST(req: NextRequest) {
const { authUserId, name, email, age, gender, occupation, hourly_rate } =
await req.json();
// ...;
return NextResponse.json({ message: "success" }, { status: 201 });
}