Remix Toast

GitHub Repo stars npm GitHub npm npm GitHub top language

用於 React router v7 / Remix.run 的簡單伺服器端 toast 管理函式庫!

此函式庫為您提供向使用者顯示 toast 通知所需的所有基本工具。客戶端實作完全由您決定,您可以使用任何您想要顯示 toast 的函式庫。

伺服器函數使用 @remix-run/server-runtime 基本元件來建立 cookie session,因此此函式庫與伺服器無關,應適用於任何伺服器設定。

如果您想深入了解其運作方式,可以在此處找到:https://alemtuzlak.hashnode.dev/handling-toasts-in-remix

安裝

npm install remix-toast

Remix.run

如果您正在使用 Remix.run,您可以使用此函式庫的 v1.2.2 或更低版本。 v2 及更高版本僅與 react-router v7 相容。

遷移到 react-router v7 的指南

如果您正在使用 react-router v7,則可以使用此函式庫的 v2.0.0 版本。您唯一需要變更的是將所有 json 方法重新命名為 data 方法,redirect 方法保持不變。例如

- import { jsonWithSuccess } from "remix-toast";
+ import { dataWithSuccess } from "remix-toast";

export const action = () => { 
- return jsonWithSuccess({ result: "Data saved successfully" }, "Operation successful! 🎉");
+ return dataWithSuccess({ result: "Data saved successfully" }, "Operation successful! 🎉");
};

設定

伺服器端

為了能夠在應用程式中的任何位置顯示 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 data({ 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 { data, type LinksFunction, type LoaderFunctionArgs } from "react-router";
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "react-router";
import { useEffect } from "react";
import { getToast } from "remix-toast";
import { ToastContainer, toast as notify } from "react-toastify";
import toastStyles from "react-toastify/ReactToastify.css?url";

// 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 data({ 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 { data, type LinksFunction, type LoaderFunctionArgs } from "react-router";
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "react-router";
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 data({ 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"]
});

使用自訂 session 建立公用程式函數

createToastUtilsWithCustomSession 是一個函數,可讓您為您的 toast 建立自訂 session。如果您想為應用程式的不同部分設定不同類型的 toast,這非常有用。

import { createCookieSessionStorage } from "react-router";
import { createToastUtilsWithCustomSession } from "remix-toast";

const session = createCookieSessionStorage({
  cookie: {
    name: "your-custom-session",
    secrets: ["some-secret"],
  },
});

export const {
  getToast,
  redirectWithToast, 
  redirectWithSuccess, 
  redirectWithError, 
  redirectWithInfo, 
  redirectWithWarning, 
  dataWithSuccess, 
  dataWithError, 
  dataWithInfo, 
  dataWithWarning 
} = 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");
};

dataWithSuccess

顯示成功 toast 訊息而不重新導向。

import { dataWithSuccess } from "remix-toast";

export const action = () => {
  return dataWithSuccess({ result: "Data saved successfully" }, "Operation successful! 🎉");
   //or with description and message (works for all the other utilities as well)
  return dataWithSuccess({ result: "Data saved successfully" }, { message: "Operation successful! 🎉", description: "description of toast" });
};

dataWithError

顯示錯誤 toast 訊息而不重新導向。

import { dataWithError } from "remix-toast";

export const action = () => {
  return dataWithError(null, "Oops! Something went wrong. Please try again later.");
};

dataWithInfo

顯示資訊 toast 訊息而不重新導向。

import { dataWithInfo } from "remix-toast";

export const action = () => {
  return dataWithInfo({ info: "Additional information" }, "Your profile has been successfully updated.");
};

dataWithWarning

顯示警告 toast 訊息而不重新導向。

import { dataWithWarning } from "remix-toast";

export const action = () => {
  return dataWithWarning({ warning: "Potential issues" }, "Your session is about to expire.");
};

謝謝

如果您想支持這個專案,可以透過給這個儲存庫加星號並與您的朋友分享來做到。

感謝這個專案的所有貢獻者和對社群的支持。你們太棒了!