Next.js 14.2.9中如何通过Server Action实现表单提交后页面刷新?
问题描述
我正在编写一个简单表单,用于更新已渲染页面的信息,希望在Next.js Server Action成功更新后端后刷新页面以显示新数据,但始终无法实现。我的Next.js版本为14.2.9。
actions.ts
'use server' import { redirect } from 'next/navigation' import { revalidatePath } from 'next/cache' export async function uploadChangedEventDetails(eventId: number, formData: FormData) { const rawFormData = { title: formData.get('title'), description: formData.get('description') } console.log(rawFormData) try { // post the changed data (this works. I've truncated the api string here) let data = await fetch(`http://.../events/${eventId}`, { method: "PATCH", cache: 'no-store', body: JSON.stringify(rawFormData) } ) let json = await data.json() console.log(json) } catch (e) { return {message: `Unable to update event with ID: ${eventId}`} } revalidatePath("/"); redirect(`/events/${eventId}`) }
components.tsx
'use client' import { useState } from "react" import { Event } from "../types" import { uploadChangedEventDetails, uploadPhoto } from "./actions" export function EventDetails({ eventData }: { eventData: Event }) { const [editing, toggleEditing] = useState(false) if (editing) { return ( <div> <button onClick={(e) => {toggleEditing(!editing)}}>Edit</button> <EventDetailsForm eventData={eventData} /> </div> ) } else { return ( <div> <button onClick={(e) => {toggleEditing(!editing)}}>Edit</button> <h1 className="text-4xl">{eventData.title}</h1> <p>{eventData.description}</p> </div> ) } } function EventDetailsForm({ eventData }: { eventData: Event }) { const uploadChangedEventDetailsWithId = uploadChangedEventDetails.bind(null, eventData.id) return ( <form action={uploadChangedEventDetailsWithId} className="flex flex-col gap-y-2 border-black border-2 rounded-lg p-2"> <input type="text" id="title" name="title" defaultValue={eventData.title} /> <input type="text" id="description" name="description" defaultValue={eventData.description} /> <input className="bg-gray-50 px-4 py-2 cursor-pointer" type="submit" value="Submit Changed Event Details" /> </form> ) }
我尝试过保留和移除try-catch的Server Action(uploadChangedEventDetails),但都无法成功触发页面刷新。我的实现方法基于Next.js路由文档内容。
解决方案
1. 修正revalidatePath的目标路径
你当前调用revalidatePath("/")是重新验证根路径,但实际需要刷新的是具体的事件详情页/events/${eventId},精准指定路径才能清除对应页面的缓存。同时补充请求头,确保后端能正确解析JSON数据,新增HTTP错误捕获逻辑(fetch仅在网络错误时进入catch,HTTP状态码错误需要手动判断)。
修改后的actions.ts:
'use server' import { redirect } from 'next/navigation' import { revalidatePath } from 'next/cache' export async function uploadChangedEventDetails(eventId: number, formData: FormData) { const rawFormData = { title: formData.get('title'), description: formData.get('description') } console.log(rawFormData) try { let data = await fetch(`http://.../events/${eventId}`, { method: "PATCH", cache: 'no-store', headers: { 'Content-Type': 'application/json' }, // 新增JSON请求头 body: JSON.stringify(rawFormData) } ) // 新增:捕获HTTP状态码错误 if (!data.ok) { throw new Error(`请求失败,状态码:${data.status}`) } let json = await data.json() console.log(json) } catch (e) { return {message: `Unable to update event with ID: ${eventId}`} } revalidatePath(`/events/${eventId}`); // 修改为具体事件页路径 redirect(`/events/${eventId}`) }
2. 确保页面数据获取的缓存策略匹配
如果你的/events/[eventId]页面通过fetch获取数据,建议为请求添加标签,后续可以通过标签精准清除缓存:
// 页面组件中获取数据的函数 async function getEventData(eventId: number) { const res = await fetch(`http://.../events/${eventId}`, { next: { tags: [`event-${eventId}`] } // 为单个事件添加专属标签 }) return res.json() }
此时Server Action中可以替换revalidatePath为revalidateTag(event-${eventId}),效果更精准。
3. 验证执行流程
可以在revalidatePath后添加console.log('路径已重新验证'),确认代码执行到这一步;如果后端返回HTTP错误,之前的代码不会进入catch,现在新增的if (!data.ok)逻辑会捕获这类错误,避免错误情况下仍执行刷新和跳转。
内容的提问来源于stack exchange,提问作者Recaptchow
相关产品推荐
相关产品推荐

