Remix Toast

GitHub Repo stars npm GitHub npm npm GitHub top language

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>
  );
}

react-toastify

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>
  );
}

react-toastify

你可以通过 `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.");
};

谢谢

如果你想支持这个项目,你可以通过为这个仓库点赞和与朋友分享来支持。

感谢这个项目的所有贡献者以及社区的支持。 你们很棒!