nextjs 和 React-hot-toast 问题

问题描述 投票:0回答:1
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
// import ToastProvider from "./(components)/Toastify";
import { Toaster } from "react-hot-toast";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>
        {children}
        <Toaster />
      </body>
    </html>
  );
}

"use client";
import { getDebugger } from "@/app/lib/debugger";
import { registerNewUser } from "@/app/lib/actions";
import FormInput from "../../(components)/forms/FormInput";
import SubmitBtn from "../../(components)/forms/SubmitBtn";
// import { toast } from "react-toastify";
import toast from "react-hot-toast";
import { useFormState } from "react-dom";

const debug = getDebugger("sign-up-form");

const initialState = {
  message: null,
};

const Page = () => {
  const [state, formAction] = useFormState(registerNewUser, initialState);
  return (
    <main>
      <form action={formAction}>
        <FormInput
          name="firstName"
          label="First Name:"
          type="text"
          placeholder="Your First Name"
        />
        <FormInput
          name="lastName"
          label="Last Name:"
          type="text"
          placeholder="Your Last Name"
        />
        <FormInput
          name="password"
          label="Password:"
          type="password"
          placeholder="******"
        />
        <FormInput
          name="confirmPassword"
          label="Confirm Password:"
          type="password"
          placeholder="******"
        />
        <FormInput
          name="email"
          label="Email:"
          type="email"
          placeholder="Your Email Here"
        />
        <SubmitBtn text="Sign Up" />
        {state?.message && toast.error(state.message)}
      </form>
    </main>
  );
};
export default Page;

"use server";
import { customFetch } from "./customFetch";
import { getDebugger } from "./debugger";

const debug = getDebugger("actions");

export const registerNewUser = async (prevState: any, formData: FormData) => {
  const user = {
    firstName: formData.get("firstName") as string,
    lastName: formData.get("lastName") as string,
    password: formData.get("password") as string,
    confirmPassword: formData.get("confirmPassword") as string,
    email: formData.get("email") as string,
  };

  try {
    const { data } = await customFetch.post("/api/auth/sign-up", user);
    return data;
  } catch (error: any) {
    return { message: error.response.data.error };
  }
};

enter image description here

请同时观看图像、按钮旁边的数字以及吐司显示的 X 次

我试图在我的nextJS应用程序中实现toastify,但由于某种原因,我得到了超过1次的toastify显示,例如我有时会得到两次toastify,有时是一次,有时是三个,依此类推..

但有一个烦人的问题让我坚持了 5 个小时!我在按钮旁边看到一个数字,您可以在图像中看到,每次我单击注册时,数字都会增加 1-2-3(取决于显示的吐司数量)

如果您需要 github 存储库,请帮我解决这个问题: https://github.com/Parselinho/handy

提前致谢

reactjs next.js next.js13 toast
1个回答
0
投票

那是因为

{state?.message && toast.error(state.message)}

您不得在 JSX 中放置任何可执行代码。每次组件重新渲染时都会重新创建 JSX。

您的代码中有两个问题:

  1. 逻辑和
    &&

在 JSX 中使用逻辑和

&&
时,它会检查左侧是否为真,然后打印右侧。
toast.error(...)
返回 toast 的
id
(数字),因此它会打印在 dom 中,如您所见。它的增加是因为每次组件重新渲染时,它都会创建具有新 id 的新 toast。

  1. JSX 中的可执行代码

除了使用 JSX 组件之外,您绝不能调用任何函数。

要实现您想要的目标,您可以使用

useEffect

useEffect(() => {
  if (state.message) toast.error(state.message)
}, [state.message])
© www.soinside.com 2019 - 2024. All rights reserved.