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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 14:13:21