Next.js中创建发票后无法更新问题求助
问题解决:Next.js中Server Actions操作本地内存数据时的副本问题
问题根源
你遇到的核心问题是:Next.js的Server Actions在每次请求时会独立加载模块,导致直接导入的invoices数组是多个独立副本。不管是本地开发还是无服务器部署环境,每次请求都会触发模块重新加载(或运行在不同实例),createInvoice和updateInvoice操作的不是同一个内存数组,自然无法找到刚创建的发票。
另外你的代码里还有一个小错误:updateInvoice中更新金额时用了amount而非转换后的amountInCents,会导致金额单位错误。
解决方案
使用单例模式封装内存数据,确保所有请求共享同一个数组实例。
步骤1:创建单例数据存储模块
新建data-store.js文件,用来统一管理发票数据:
// data-store.js import { invoices as initialInvoices } from './placeholder-data'; // 初始化单例数组 let invoices = [...initialInvoices]; // 获取当前发票列表 export const getInvoices = () => invoices; // 更新发票列表 export const setInvoices = (newInvoices) => { invoices = newInvoices; };
步骤2:修改Server Actions代码
替换原来直接导入invoices的方式,改用单例存储的方法:
'use server'; import { z } from 'zod'; import { getInvoices, setInvoices } from './data-store'; import { revalidatePath } from 'next/cache'; import { redirect } from 'next/navigation'; const FormSchema = z.object({ id: z.string(), customerId: z.string(), amount: z.coerce.number(), status: z.enum(['pending', 'paid']), date: z.string(), }); const CreateInvoice = FormSchema.omit({ id: true, date: true }); export async function createInvoice(formData: FormData) { const { customerId, amount, status } = CreateInvoice.parse({ customerId: formData.get('customerId'), amount: formData.get('amount'), status: formData.get('status'), }); const amountInCents = amount * 100; const date = new Date().toISOString().split('T')[0]; const currentInvoices = getInvoices(); const newInvoice = { id: currentInvoices.length.toString(), customer_id: customerId, amount: amountInCents, status: status, date: date, }; // 创建新数组并更新单例存储 const updatedInvoices = [...currentInvoices, newInvoice]; setInvoices(updatedInvoices); revalidatePath('/dashboard/invoices'); redirect('/dashboard/invoices'); } const UpdateInvoice = FormSchema.omit({ id: true, date: true }); export async function updateInvoice(id: string, formData: FormData) { const { customerId, amount, status } = UpdateInvoice.parse({ customerId: formData.get('customerId'), amount: formData.get('amount'), status: formData.get('status'), }); const amountInCents = amount * 100; const currentInvoices = getInvoices(); const fetchedInvoiceIndex = currentInvoices.findIndex((inv) => inv.id === id); if (fetchedInvoiceIndex !== -1) { // 创建新数组并更新指定发票(避免直接修改原数组) const updatedInvoices = [...currentInvoices]; updatedInvoices[fetchedInvoiceIndex] = { ...updatedInvoices[fetchedInvoiceIndex], customer_id: customerId, amount: amountInCents, // 修正金额单位错误 status: status, }; setInvoices(updatedInvoices); revalidatePath('/dashboard/invoices'); redirect('/dashboard/invoices'); } else { console.error('Invoice not found'); } }
注意事项
- 这种内存存储仅适合本地开发测试,服务器重启后数据会全部丢失。
- 生产环境必须使用数据库(如PostgreSQL、MongoDB等)来持久化数据。
内容的提问来源于stack exchange,提问作者ApexCowboy
相关产品推荐
相关产品推荐

