纯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
相关产品推荐
相关产品推荐

