Next.js13使用Server Action提交表单报错:backingFormData.forEach is not a function
解决Next.js 13中Server Action报错
Error: backingFormData.forEach is not a function的问题 可能原因及解决方案
1. 确认Next.js版本并升级
Server Action在Next.js 13.4及以上版本才进入稳定支持阶段,若你的版本低于13.4,需先升级:
npm install next@latest react@latest react-dom@latest
2. 正确配置next.config.js
确保配置文件中启用Server Action(13.4+版本App Router默认支持,但部分场景仍需显式配置):
/** @type {import('next').NextConfig} */ const nextConfig = { experimental: { serverActions: true, }, }; module.exports = nextConfig;
配置完成后重启开发服务器。
3. 调整Server Action的写法
方案一:将Server Action移至组件外部
避免在异步页面组件内部定义Server Action,将其提取到组件外部:
import { useState} from 'react' export interface Product { id?: number; product: string; price: string; } // Server Action移至组件外部,"use server"单独占一行 async function addProductToDatabase(e: FormData) { "use server"; const product = e.get("product")?.toString(); const price = e.get("price")?.toString(); if (!product || !price) return; const newProduct: Product = { product, price }; await fetch('https://64bda1242320b36433c7c958.mockapi.io/product', { method: 'POST', body: JSON.stringify(newProduct), headers: { 'Content-Type':'application/json' } }); } export default async function Home() { const res = await fetch( "https://64bda1242320b36433c7c958.mockapi.io/product", { cache: "no-cache", } ); const products: Product[] = await res.json(); return ( <main> <h1 className="text-3xl font-bold text-center"> Testing product server function </h1> <form action={addProductToDatabase} className="flex flex-col gap-5 max-w-xl mx-auto p-5" > <input name="product" type="text" className="border border-gray-300 p-2 rounded-md" placeholder="Enter product name" /> <input name="price" type="text" className="border border-gray-300 p-2 rounded-md" placeholder="Enter product price" /> <button className="border bg-blue-500 text-white p-2 rounded-md"> Add product </button> </form> <h2 className="font-bold p-5">list of products</h2> <div className="flex flex-wrap gap-5"> {products.map((product) => ( <div key={product.id} className="p-5 shadow"> <p>{product.product}</p> <p>R$: {product.price}</p> </div> ))} </div> </main> ); }
方案二:将Server Action单独拆分到文件中
推荐将Server Action集中管理,创建app/actions.ts文件:
"use server"; export interface Product { id?: number; product: string; price: string; } export async function addProductToDatabase(formData: FormData) { const product = formData.get("product")?.toString(); const price = formData.get("price")?.toString(); if (!product || !price) return; const newProduct: Product = { product, price }; await fetch('https://64bda1242320b36433c7c958.mockapi.io/product', { method: 'POST', body: JSON.stringify(newProduct), headers: { 'Content-Type':'application/json' } }); }
然后在页面组件中导入使用:
import { addProductToDatabase, Product } from './actions'; export default async function Home() { const res = await fetch( "https://64bda1242320b36433c7c958.mockapi.io/product", { cache: "no-cache" } ); const products: Product[] = await res.json(); return ( <main> <h1 className="text-3xl font-bold text-center"> Testing product server function </h1> <form action={addProductToDatabase} className="flex flex-col gap-5 max-w-xl mx-auto p-5" > <input name="product" type="text" className="border border-gray-300 p-2 rounded-md" placeholder="Enter product name" /> <input name="price" type="text" className="border border-gray-300 p-2 rounded-md" placeholder="Enter product price" /> <button className="border bg-blue-500 text-white p-2 rounded-md"> Add product </button> </form> <h2 className="font-bold p-5">list of products</h2> <div className="flex flex-wrap gap-5"> {products.map((product) => ( <div key={product.id} className="p-5 shadow"> <p>{product.product}</p> <p>R$: {product.price}</p> </div> ))} </div> </main> ); }
4. 检查页面组件的渲染模式
若你使用的是Page Router(pages目录下的组件),Server Action的启用方式略有不同:
- 同样需要在
next.config.js中启用serverActions - Server Action需定义在
pages目录下的文件中,或单独的action文件,并确保"use server"指令正确
关键注意点
"use server"指令必须单独占据一行,不能与其他代码同行- Server Action的参数必须是
FormData类型,无需手动解析表单数据,Next.js会自动传递 - 确保开发服务器在修改配置后重启,否则配置不会生效
内容的提问来源于stack exchange,提问作者alexRicc2
相关产品推荐
相关产品推荐

