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

纯Next.js React Server Component中如何展示表单Server Action错误

在React Server Component中处理Server Action错误并反馈给用户

在纯Server Component场景下,要把Server Action里捕获的错误返回给前端用户,核心是通过服务器端状态传递实现,下面提供两种实用方案:

方案一:URL搜索参数传递错误信息

利用Next.js的redirectAPI,把错误信息编码后通过URL参数带回页面,Server Component读取参数后直接渲染错误提示:

import { redirect } from 'next/navigation';

// 页面组件接收searchParams参数
export default function Page({ searchParams }: { searchParams: { error?: string } }) {
  async function create(formData: FormData) {
    'use server';

    try {
      // 模拟数据变更逻辑(比如写入数据库)
      const title = formData.get('title') as string;
      if (!title.trim()) throw new Error('标题不能为空');
      
      // 操作成功后跳转(避免表单重复提交)
      redirect('/');
    } catch (error) {
      // 提取错误信息并编码,避免特殊字符破坏URL
      const errorMsg = error instanceof Error ? error.message : '发生未知错误';
      redirect(`/?error=${encodeURIComponent(errorMsg)}`);
    }
  }

  return (
    <div className="container">
      {/* 渲染错误提示(如果存在) */}
      {searchParams.error && (
        <div style={{ color: '#dc2626', padding: '0.5rem 1rem', marginBottom: '1rem', backgroundColor: '#fee2e2', borderRadius: '4px' }}>
          {decodeURIComponent(searchParams.error)}
        </div>
      )}
      <form action={create} method="POST">
        <div style={{ marginBottom: '0.5rem' }}>
          <label htmlFor="title">标题:</label>
          <input type="text" id="title" name="title" placeholder="请输入标题" style={{ marginLeft: '0.5rem' }} />
        </div>
        <button type="submit">提交</button>
      </form>
    </div>
  );
}

方案二:Cookie存储错误信息(更优雅)

如果不想在URL中暴露错误内容,可以用临时Cookie存储错误信息,页面渲染后立即清除Cookie:

import { redirect } from 'next/navigation';
import { cookies } from 'next/headers';

export default function Page() {
  // 读取并清除临时Cookie中的错误信息
  const errorMsg = cookies().get('actionError')?.value;
  if (errorMsg) {
    cookies().delete('actionError');
  }

  async function create(formData: FormData) {
    'use server';

    try {
      const title = formData.get('title') as string;
      if (!title.trim()) throw new Error('标题不能为空');
      
      // 数据变更操作
      redirect('/');
    } catch (error) {
      const msg = error instanceof Error ? error.message : '发生未知错误';
      // 设置临时Cookie,5秒后过期(避免残留)
      cookies().set('actionError', msg, { maxAge: 5, path: '/' });
      redirect('/');
    }
  }

  return (
    <div className="container">
      {errorMsg && (
        <div style={{ color: '#dc2626', padding: '0.5rem 1rem', marginBottom: '1rem', backgroundColor: '#fee2e2', borderRadius: '4px' }}>
          {errorMsg}
        </div>
      )}
      <form action={create} method="POST">
        <div style={{ marginBottom: '0.5rem' }}>
          <label htmlFor="title">标题:</label>
          <input type="text" id="title" name="title" placeholder="请输入标题" style={{ marginLeft: '0.5rem' }} />
        </div>
        <button type="submit">提交</button>
      </form>
    </div>
  );
}

关键注意点

  • 两种方案都完全基于Server Component实现,无需任何客户端组件代码。
  • 提交成功后建议执行redirect,避免用户刷新页面重复提交表单。
  • 错误信息需要做编码/解码处理,防止特殊字符导致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:35:21