You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js管理页创建用户报错:仅允许普通对象从Server Components传客户端组件

问题根源

报错的核心原因是Server Action(createUserAction)返回了Response类实例,Next.js不允许从Server Component/Server Action向Client Component传递类实例或非纯plain对象。虽然用户创建操作已成功执行(数据库插入完成),但返回的Response对象在客户端渲染时触发了类型检查错误。

修复步骤

1. 修改Server Action,避免返回类实例

修改actions.ts中的createUserAction,不要直接返回createUser的结果(即Response对象),改为处理响应后返回纯对象,或直接不返回值:

'use server'
import { createUser, deleteUser } from '@/api';
import { revalidatePath } from "next/cache";

export async function createUserAction(formData: FormData) {
  const { name, email, age } = Object.fromEntries(formData);
  revalidatePath('/admin');
  
  // 处理fetch响应,不返回Response实例
  const response = await createUser(name as string, email as string, age as string);
  if (!response.ok) {
    const errorData = await response.json();
    throw new Error(errorData.error || '创建用户失败');
  }
  
  // 返回纯对象,或直接省略return
  return await response.json();
}

export async function deleteUserAction(id: number) {
  revalidatePath('/admin')
  await deleteUser(id);
}

2. 优化api.ts中的createUser函数(推荐)

让createUser直接返回解析后的JSON数据,而非原始Response,简化Server Action代码:

export const BASE_URL = 'http://localhost:3000';
export async function createUser(name: string, email: string, age: string) {
  const response = await fetch(BASE_URL + '/api/create-user', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' }, // 需添加该Header,否则后端无法解析JSON
    body: JSON.stringify({ name, email, age }),
  });
  
  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error);
  }
  
  return response.json();
}

3. 确保API返回纯对象(可选)

在api/create-user/route.ts中,将SQL查询结果转换为纯对象数组,避免Vercel Postgres返回的结果带有额外属性:

import { sql } from '@vercel/postgres';
import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  const { name, email, age } = await request.json();

  try {
    if (!name || !email || !age) throw new Error('请填写所有字段');

    await sql`INSERT INTO users (name, email, age) VALUES (${name}, ${email}, ${age});`;
  } catch (error) {
    return NextResponse.json({ error: (error as Error).message }, { status: 500 });
  }

  const { rows: users } = await sql`SELECT * FROM users;`; // 取rows字段,得到纯用户数组

  return NextResponse.json({ users }, { status: 200 });
}

4. 客户端组件添加错误处理(可选)

在AddUser.tsx中,利用useActionState捕获Server Action抛出的错误,提升用户体验:

'use client'

import { createUserAction } from '@/app/actions.ts';
import React, { useActionState } from 'react';

export default function AddUser() {
    const [open, setOpen] = React.useState(false);
    const [error, createUserWithState] = useActionState(createUserAction, undefined);

    function handleOpen() {
        setOpen(true);
    }

    return (
        <div>
            <button onClick={handleOpen} className='bg-slate-400 p-3 rounded-xl mb-10 mt-[200px]'>Add new user</button>
            {open && (
                <form 
                    action={(formData) => {
                        createUserWithState(formData);
                        setOpen(false); // 提交后关闭表单
                    }} 
                    className="translate-x-[-50%] left-[50%] rounded-xl h-[400px] flex flex-col gap-4 w-[500px] text-black absolute bg-slate-700 p-10 py-20"
                >
                    {error && <p className="text-red-400">{error.message}</p>}
                    <input type="text" name="name" className='h-[40px] rounded-lg' placeholder="姓名"/>
                    <input type="email" name="email" className='h-[40px] rounded-lg' placeholder="邮箱"/>
                    <input type="number" name="age" className='h-[40px] rounded-lg' placeholder="年龄"/>
                    <button type="submit" className="bg-red-500 text-white h-[40px] rounded-lg mt-auto">
                        创建用户
                    </button>
                </form>
            )}
        </div>
    )
}
为什么之前的尝试无效?

你之前将AddUser移到Admin页面并移除"use client",但Admin本身是Server Component,表单调用Server Action时,返回的Response实例仍会被Next.js尝试传递,导致相同错误。核心问题始终是Server Action返回了非纯对象。

内容的提问来源于stack exchange,提问作者Ucha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:12:33