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

Next.js 13中如何在Server Action后调用Toast通知

Next.js 13 Server Action 完成数据变更后触发客户端 Toast 方案

Server Action 运行在服务端,无法直接调用客户端的 Hook/Context,核心思路是通过服务端返回的操作结果,在客户端组件中触发 Toast,以下是几种实用实现方式:

方案一:直接调用 Server Action 并处理返回结果

在客户端组件中调用 Server Action,根据返回的成功/失败状态触发 Toast:

1. 定义 Server Action

// app/actions.ts
'use server';

export async function updateData(formData: FormData) {
  try {
    // 执行数据变更逻辑(比如数据库操作)
    // await db.item.update({ ... });
    return { success: true, message: '数据更新成功' };
  } catch (error) {
    return { success: false, message: '数据更新失败:' + (error as Error).message };
  }
}

2. 客户端组件调用并触发 Toast

// app/components/UpdateForm.tsx
'use client';

import { updateData } from '../actions';
import { useToast } from '../context/ToastContext';

export default function UpdateForm() {
  const { showToast } = useToast();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget as HTMLFormElement);
    
    const result = await updateData(formData);
    // 根据返回结果触发 Toast
    showToast({
      type: result.success ? 'success' : 'error',
      content: result.message
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="content" placeholder="输入内容" />
      <button type="submit">提交更新</button>
    </form>
  );
}

方案二:使用 useFormState 监听提交状态

利用 React 的 useFormState 绑定 Server Action,通过状态变化自动触发 Toast:

// app/components/UpdateForm.tsx
'use client';

import { useFormState, useFormStatus } from 'react-dom';
import { updateData } from '../actions';
import { useToast } from '../context/ToastContext';
import { useEffect } from 'react';

// 初始化提交状态
const initialState = { success: false, message: '' };

export default function UpdateForm() {
  const { showToast } = useToast();
  const [submitState, formAction] = useFormState(updateData, initialState);

  // 监听提交状态变化,触发 Toast
  useEffect(() => {
    if (submitState.message) {
      showToast({
        type: submitState.success ? 'success' : 'error',
        content: submitState.message
      });
    }
  }, [submitState, showToast]);

  // 可选:获取提交中状态,禁用按钮
  const { pending } = useFormStatus();

  return (
    <form action={formAction}>
      <input type="text" name="content" placeholder="输入内容" />
      <button type="submit" disabled={pending}>
        {pending ? '提交中...' : '提交更新'}
      </button>
    </form>
  );
}

方案三:服务器组件中触发的处理方式

如果需要在服务器组件中触发操作,需将交互逻辑封装到客户端子组件中:

1. 服务器页面

// app/page.tsx
import UpdateButton from './components/UpdateButton';

export default function HomePage() {
  return (
    <div>
      <h1>数据管理页面</h1>
      {/* 服务器组件无法直接处理交互,使用客户端组件封装 */}
      <UpdateButton />
    </div>
  );
}

2. 客户端按钮组件

// app/components/UpdateButton.tsx
'use client';

import { updateData } from '../actions';
import { useToast } from '../context/ToastContext';

export default function UpdateButton() {
  const { showToast } = useToast();

  const handleClick = async () => {
    const result = await updateData(new FormData());
    showToast({
      type: result.success ? 'success' : 'error',
      content: result.message
    });
  };

  return <button onClick={handleClick}>执行数据更新</button>;
}

关键注意事项

  • 所有调用 Toast Hook/Context 的组件必须添加 'use client' 指令,确保运行在客户端。
  • Server Action 仅负责服务端逻辑,不要在其中包含任何客户端相关代码(如 Hook 调用)。
  • 如果使用第三方 Toast 库(如 react-hot-toast),逻辑完全通用,只需替换 showToast 为对应库的调用方法即可。

内容的提问来源于stack exchange,提问作者Re-Angelo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 05:12:37