如何在 Nextjs13 中的服务器操作后调用通知/toast

问题描述 投票:0回答:2

您好,我正在努力找出如何在 Nextjs 13 中使用服务器操作成功进行数据突变后调用 toast。toast 是一个客户端组件,因为它使用钩子/上下文。

我该怎么做?

javascript reactjs next.js ecmascript-6 next.js13
2个回答
0
投票

简短的回答,没有规范的方法可以做到这一点。 有解决方法。尽管它们可能相关,但根据您渲染的是服务器还是客户端组件,它们可能会有所不同。

  • 选项一:在服务器操作上设置 cookie 并在下一个请求时读取它(当用户重定向回页面时)。您可以将 cookie 设置为较短的过期时间。你可以在 cookie 中放入你想要的任何内容,并根据它渲染你的吐司。
  • 选项二:在服务器上创建一个全局状态并在其中放入您想要的任何内容。您应该使用请求的身份来标识要设置的状态,否则您可能会向错误的用户显示 toast。
  • 选项三:使用某种会话管理器并将 toast 消息放在会话上。根据您要管理的会话类型,这可能位于标头、cookie、内存等中。

老实说,next 没有提供开箱即用的解决方案,让用户想出他们能想到的任何解决方案,包括可能的糟糕解决方案,这很糟糕。

参见 cookie 示例:

// Server action file
"use server";
import { cookies } from "next/headers";
...

// At the end of your server action function:
cookies()
  .set(
    "my-app-toast-msg",
    JSON.stringify({error: true, msg: "wrong credentials"}, {
      expires: new Date(Date.now() + 10 * 1000), // 10 seconds
    })
  );
// At your server component file
import { cookies } from "next/headers";

export async function Page() {
  const toastMsg = cookies().get("my-app-toast-msg");

  return (
    <>
      {!!toastMsg &&
        JSON.parse(toastMsg).error &&
        <ClientErrorToast errorMsg={JSON.parse(toastMsg).msg} />
      ...
    </>
  )
}

这是一个快速的、肮脏的、未经测试的内存实现,我不知道这是否是一个好的解决方案。 我使用一个错误作为例子,但你应该能够看到这个想法。


0
投票

我能够使用

useFormStatus()
钩子实现此结果。

假设您有一个使用服务器操作的表单组件。这是一个基本的服务器组件,可能会调用您的服务器操作,在另一个文件中定义:

import { submit } from "./serverAction";

export function ServerForm() {
  return (
    <form action={submit}>
      <input type="email" name="email" />
      <input type="text" name="name" />
      <input type="submit" />
    </form>
  );
}

要管理服务器操作返回的数据,例如,显示每个输入附近的错误,您需要将此表单转换为客户端组件:

"use client"

import { submit } from "./serverAction";
// @ts-ignore: Experimental feature not yet in react-dom type definitions
import { experimental_useFormState as useFormState } from "react-dom";

export function ClientForm() {
  // You pass your ServerAction and an initial state to `useFormState`
  const [state, formAction] = useFormState(submit, {
    error: { name: null, email: null },
    message: null,
  });

  return (
    <form action={formAction}>
      <input type="email" name="email" />
      <p>{state?.error?.email}</p>
      <input type="text" name="name" />
      <p>{state?.error?.name}</p>
      <input type="submit" />
    </form>
  );
}

在这种情况下,我从 ServerAction 返回一个对象:

"use server";

export async function submit(formData: FormData) {
  // Extract data from the submitted form
  const name = formData.get("name") as string;
  const email = formData.get("email") as string;

  try {
    // You might do data validation and database interactions here
    // On success, you'd probably redirect instead of returning an object
    return { error: null, message: `New submission: ${name} - ${email}` };
  } catch (e) {
    // Error handling
    return {
      error: {
        name: "There was an error with this name",
        email: "There was an error with this email",
      },
      message: "Failed submission",
    };
  }
}

您可以通过设置观察

useEffect
state
来无缝触发烤面包机。例如,使用 shadcn 的 toaster:

"use client";

import { useToast } from "@components/shadcn-ui-registry/use-toast";
import { useEffect } from "react";
import { submit } from "./serverAction";
// @ts-ignore: Experimental feature not yet in react-dom type definitions
import { experimental_useFormState as useFormState } from "react-dom";

export function ClientForm() {
  // You pass your ServerAction and an initial state to `useFormState`
  const [state, formAction] = useFormState(submit, {
    error: { name: null, email: null },
    message: null,
  });

  const { toast } = useToast();
  useEffect(() => {
    toast({
      title: state?.error?.name || state?.error?.email ? "Error" : "Success",
      description: state.message,
    });
  }, [state, toast]);

  return (
    <form action={formAction}>
      <input type="email" name="email" />
      <p>{state?.error?.email}</p>
      <input type="text" name="name" />
      <p>{state?.error?.name}</p>
      <input type="submit" />
    </form>
  );
}

有关更多详细信息,请参阅Next.js 表单和突变文档。希望这对您有所帮助,请随时提供反馈或询问任何不清楚的地方。

© www.soinside.com 2019 - 2024. All rights reserved.