全书目录

第五篇:Next.js 完全指南 —— 商业综合体宇宙

第七章:写入数据 —— 表单不是“额外系统”,而是运营主通道

1 分钟 445 字 第 118 / 962 个阅读单元

React 官方把 'use server' 这类函数叫 Server Functions
Next.js 生态里大家更常把它叫 Server Actions
本章为了贴近 Next.js 社区习惯,继续用“Server Actions”这个叫法。

#1. 最符合 Next.js 心智的写法:表单直接提交到服务端函数
tsx
// app/products/actions.ts
'use server';

import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';

export async function createProduct(formData: FormData) {
  const name = String(formData.get('name') ?? '').trim();

  if (!name) {
    throw new Error('商品名不能为空');
  }

  // await db.product.create({ data: { name } });

  revalidatePath('/products');
  redirect('/products');
}
tsx
// app/products/new/page.tsx
import { createProduct } from '../actions';

export default function NewProductPage() {
  return (
    <form action={createProduct}>
      <input name="name" placeholder="商品名" />
      <button type="submit">创建商品</button>
    </form>
  );
}

这条链路非常像真实商业系统:

text
顾客/运营人员填写表单
   ↓
表单直接提交给服务端动作
   ↓
服务端写数据库
   ↓
让商品列表失效重算
   ↓
跳回最新页面
#2. 什么时候它比前端 fetch 更自然?

当你的场景是:

  • 表单提交
  • CRUD 写入
  • 页面提交后刷新结果
  • 要和缓存失效联动

这时候 Server Actions 非常顺手。

#3. 前台要即时反馈时,再加 Client 侧增强

比如禁用按钮、显示 pending、显示表单错误,这时你可以在 Client Component 里配合 React 的表单状态 Hook 做增强。

tsx
'use client';

import { useActionState } from 'react';
import { createProduct } from '../actions';

const initialState = { message: '' };

export default function ProductForm() {
  const [state, formAction, pending] = useActionState(createProduct, initialState);

  return (
    <form action={formAction}>
      <input name="name" placeholder="商品名" />
      <button disabled={pending}>
        {pending ? '提交中...' : '创建商品'}
      </button>
      <p>{state.message}</p>
    </form>
  );
}

你可以把它理解成:

  • Server Action 负责真的改系统
  • Client Component 负责把“正在提交”“提交失败”“乐观反馈”这些交互体验补齐