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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:25:29