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 };
}
};
请同时观看图像、按钮旁边的数字以及吐司显示的 X 次
我试图在我的nextJS应用程序中实现toastify,但由于某种原因,我得到了超过1次的toastify显示,例如我有时会得到两次toastify,有时是一次,有时是三个,依此类推..
但有一个烦人的问题让我坚持了 5 个小时!我在按钮旁边看到一个数字,您可以在图像中看到,每次我单击注册时,数字都会增加 1-2-3(取决于显示的吐司数量)
如果您需要 github 存储库,请帮我解决这个问题: https://github.com/Parselinho/handy
提前致谢
那是因为
{state?.message && toast.error(state.message)}
您不得在 JSX 中放置任何可执行代码。每次组件重新渲染时都会重新创建 JSX。
您的代码中有两个问题:
&&
在 JSX 中使用逻辑和
&&
时,它会检查左侧是否为真,然后打印右侧。 toast.error(...)
返回 toast 的 id
(数字),因此它会打印在 dom 中,如您所见。它的增加是因为每次组件重新渲染时,它都会创建具有新 id 的新 toast。
除了使用 JSX 组件之外,您绝不能调用任何函数。
要实现您想要的目标,您可以使用
useEffect
useEffect(() => {
if (state.message) toast.error(state.message)
}, [state.message])