Remix Toast
Remix.run 的简单服务器端 Toast 管理库!
这个库为你提供了向用户展示 Toast 通知可能需要的所有必要工具。 客户端实现完全由你决定,你可以使用任何你想要用来展示 Toast 的库。
服务器函数使用 @remix-run/server-runtime 原语来创建一个 Cookie 会话,因此该库与服务器无关,应该适用于任何服务器设置。
如果你想阅读关于这个库工作原理的深入解释,可以在这里找到:https://alemtuzlak.hashnode.dev/handling-toasts-in-remix
安装
npm install remix-toast
设置
服务器端
为了能够在应用程序中的任何地方显示 Toast,你需要将以下代码添加到你的 `root.tsx` 文件中。
import { getToast } from "remix-toast";
export const loader = async ({ request }: LoaderFunctionArgs) => {
// Extracts the toast from the request
const { toast, headers } = await getToast(request);
// Important to pass in the headers so the toast is cleared properly
return json({ toast }, { headers });
}
export default function App({ children }: { children: ReactNode }) {
const { toast } = useLoaderData<typeof loader>();
useEffect(() => {
if(toast){
// Call your toast function here
alert(toast.message);
}
}, [toast])
return (
...
);
}
客户端
之后,你可以使用你喜欢的任何 Toast 通知库,但这里是一些示例
react-toastify
import { json, type LinksFunction, type LoaderFunctionArgs } from "@remix-run/node";
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "@remix-run/react";
import { useEffect } from "react";
import { getToast } from "remix-toast";
import { ToastContainer, toast as notify } from "react-toastify";
import toastStyles from "react-toastify/dist/ReactToastify.css";
// Add the toast stylesheet
export const links: LinksFunction = () => [{ rel: "stylesheet", href: toastStyles }];
// Implemented from above
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { toast, headers } = await getToast(request);
return json({ toast }, { headers });
};
export default function App() {
const { toast } = useLoaderData<typeof loader>();
// Hook to show the toasts
useEffect(() => {
if (toast) {
// notify on a toast message
notify(toast.message, { type: toast.type });
}
}, [toast]);
return (
<html lang="en">
<head>
...
</head>
<body>
...
{/* Add the toast container */}
<ToastContainer />
</body>
</html>
);
}
Sonner
import { json, type LinksFunction, type LoaderFunctionArgs } from "@remix-run/node";
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "@remix-run/react";
import { useEffect } from "react";
import { getToast } from "remix-toast";
import { Toaster, toast as notify } from "sonner";
// Implemented from above
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { toast, headers } = await getToast(request);
return json({ toast }, { headers });
};
export default function App() {
const { toast } = useLoaderData<typeof loader>();
// Hook to show the toasts
useEffect(() => {
if (toast?.type === "error") {
notify.error(toast.message);
}
if (toast?.type === "success") {
notify.success(toast.message);
}
}, [toast]);
return (
<html lang="en">
<head>...</head>
<body>
...
{/* Add the toast container */}
<Toaster />
</body>
</html>
);
}
覆盖 Cookie 选项
你可以通过 `setToastCookieOptions` 函数传入自己的选项来覆盖默认的 Cookie 选项。
import { setToastCookieOptions } from "remix-toast";
setToastCookieOptions({
secrets:
process.env.NODE_ENV === "production"
? [process.env.SESSION_SECRET]
: ["secret"]
});
使用自定义会话创建实用程序函数
createToastUtilsWithCustomSession
是一个允许你为 Toast 创建自定义会话的函数。 这在你想为应用程序的不同部分拥有不同类型的 Toast 时很有用。
import { createCookieSessionStorage } from "@remix-run/node";
import { createToastUtilsWithCustomSession } from "remix-toast";
const session = createCookieSessionStorage({
cookie: {
name: "your-custom-session",
secrets: ["some-secret"],
},
});
export const {
getToast,
redirectWithToast,
redirectWithSuccess,
redirectWithError,
redirectWithInfo,
redirectWithWarning,
jsonWithSuccess,
jsonWithError,
jsonWithInfo,
jsonWithWarning
} = createToastUtilsWithCustomSession(session);
实用程序
redirectWithToast
允许你重定向到新路由并显示 Toast 消息的通用函数。
import { redirectWithToast } from "remix-toast";
export const action = () => {
return redirectWithToast("/login", { message: "You need to login to access this page", description: "description of toast", type: "error" });
}
redirectWithSuccess
重定向到新路由并显示成功 Toast 消息。
import { redirectWithSuccess } from "remix-toast";
export const action = () => {
return redirectWithSuccess("/login", "You are logged in!");
//or with description and message (works for all the other utilities as well)
return redirectWithSuccess("/login", { message: "You are logged in!", description: "description of toast" });
}
redirectWithError
重定向到新路由并显示错误 Toast 消息。
import { redirectWithError } from "remix-toast";
export const action = () => {
return redirectWithError("/login", "You need to login to access this page");
}
redirectWithInfo
重定向到新路由并显示信息 Toast 消息。
import { redirectWithInfo } from "remix-toast";
export const action = () => {
return redirectWithInfo("/login", "You need to login to access this page");
};
redirectWithWarning
重定向到新路由并显示警告 Toast 消息。
import { redirectWithWarning } from "remix-toast";
export const action = () => {
return redirectWithWarning("/login", "You need to login to access this page");
};
jsonWithSuccess
在不进行重定向的情况下显示成功 Toast 消息。
import { jsonWithSuccess } from "remix-toast";
export const action = () => {
return jsonWithSuccess({ result: "Data saved successfully" }, "Operation successful! 🎉");
//or with description and message (works for all the other utilities as well)
return jsonWithSuccess({ result: "Data saved successfully" }, { message: "Operation successful! 🎉", description: "description of toast" });
};
jsonWithError
在不进行重定向的情况下显示错误 Toast 消息。
import { jsonWithError } from "remix-toast";
export const action = () => {
return jsonWithError(null, "Oops! Something went wrong. Please try again later.");
};
jsonWithInfo
在不进行重定向的情况下显示信息 Toast 消息。
import { jsonWithInfo } from "remix-toast";
export const action = () => {
return jsonWithInfo({ info: "Additional information" }, "Your profile has been successfully updated.");
};
jsonWithWarning
在不进行重定向的情况下显示警告 Toast 消息。
import { jsonWithWarning } from "remix-toast";
export const action = () => {
return jsonWithWarning({ warning: "Potential issues" }, "Your session is about to expire.");
};
谢谢
如果你想支持这个项目,你可以通过为这个仓库点赞和与朋友分享来支持。
感谢这个项目的所有贡献者以及社区的支持。 你们很棒!