Next.js App Router中如何处理POST请求并在另一页面展示数据?
解决方案:Next.js App Router 无JS表单提交并展示数据
核心思路
借助App Router的route.ts处理POST请求,将提交的数据通过临时Cookie或URL查询参数传递给/bar页面,再在/bar的服务器组件中读取并展示数据,全程无需JS介入。
实现步骤
1. /foo页面:渲染无JS表单
创建客户端组件(适配next-intl的客户端需求),表单直接指向/bar的POST路由:
'use client'; import { useTranslations } from 'next-intl'; export default function FooPage() { const t = useTranslations('Foo'); // 对应你的国际化配置key return ( <form method="POST" action="/bar" className="space-y-4"> <div> <label htmlFor="name" className="block mb-1"> {t('nameLabel')} </label> <input type="text" id="name" name="name" required className="w-full p-2 border rounded" /> </div> <div> <label htmlFor="email" className="block mb-1"> {t('emailLabel')} </label> <input type="email" id="email" name="email" required className="w-full p-2 border rounded" /> </div> <button type="submit" className="px-4 py-2 bg-blue-500 text-white rounded"> {t('submitBtn')} </button> </form> ); }
2. /bar/route.ts:处理POST请求
创建路由文件接收表单数据,这里用临时Cookie传递数据(避免URL暴露,优化体验):
import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; export async function POST(request: Request) { // 解析表单数据 const formData = await request.formData(); const name = formData.get('name') as string; const email = formData.get('email') as string; // 数据验证(按需添加,比如邮箱格式校验) if (!name || !email.includes('@')) { redirect(`/foo?error=invalid-data`); } // 设置临时Cookie,仅在/bar路径有效,1分钟后自动过期 cookies().set('submittedFormData', JSON.stringify({ name, email }), { maxAge: 60, httpOnly: true, path: '/bar', secure: process.env.NODE_ENV === 'production', }); // 重定向到/bar页面展示数据 redirect('/bar'); }
3. /bar页面:读取并展示提交数据
创建服务器组件,读取Cookie中的数据,展示后立即删除Cookie避免重复显示:
import { cookies } from 'next/headers'; import { useTranslations } from 'next-intl'; export default async function BarPage() { const t = useTranslations('Bar'); const cookieStore = cookies(); const formDataCookie = cookieStore.get('submittedFormData'); let submittedData = null; if (formDataCookie) { // 解析Cookie数据 submittedData = JSON.parse(formDataCookie.value); // 读取后立即删除Cookie,防止刷新页面仍显示数据 cookieStore.delete('submittedFormData'); } return ( <div className="max-w-md mx-auto mt-8"> <h1 className="text-2xl font-bold mb-4">{t('successTitle')}</h1> {submittedData ? ( <div className="p-4 border rounded bg-gray-50"> <p className="mb-2"> <span className="font-medium">{t('nameLabel')}:</span> {submittedData.name} </p> <p> <span className="font-medium">{t('emailLabel')}:</span> {submittedData.email} </p> </div> ) : ( <p className="text-gray-600">{t('noDataMessage')}</p> )} </div> ); }
可选方案:用URL查询参数传递数据
如果不介意数据暴露在URL中,可简化路由处理:
// /bar/route.ts import { redirect } from 'next/navigation'; export async function POST(request: Request) { const formData = await request.formData(); const name = encodeURIComponent(formData.get('name') as string); const email = encodeURIComponent(formData.get('email') as string); redirect(`/bar?name=${name}&email=${email}`); }
然后在/bar页面通过searchParams读取:
export default function BarPage({ searchParams }: { searchParams: { name?: string; email?: string } }) { const t = useTranslations('Bar'); const name = searchParams.name; const email = searchParams.email; return ( <div> <h1>{t('successTitle')}</h1> {name && email ? ( <div> <p>{t('nameLabel')}: {name}</p> <p>{t('emailLabel')}: {email}</p> </div> ) : ( <p>{t('noDataMessage')}</p> )} </div> ); }
注意事项
- 数据验证:务必在
POST路由中验证表单数据,防止无效或恶意数据流入 - next-intl适配:客户端组件需添加
'use client'指令才能使用useTranslations - Cookie安全:生产环境下设置
secure: true,确保Cookie仅通过HTTPS传输
内容的提问来源于stack exchange,提问作者Ionuț Staicu
相关产品推荐
相关产品推荐

