From d71e8c2396dc91e883f5fff1ebfe9a6be08b198a Mon Sep 17 00:00:00 2001 From: Naoki Date: Sun, 18 Feb 2024 19:54:21 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=B7=E3=82=B9=E3=83=86=E3=83=A0=E3=83=A1?= =?UTF-8?q?=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92=E3=83=88=E3=83=BC?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=81=A7=E8=A1=A8=E7=A4=BA=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system-message/system-message-context.ts | 9 ++++ .../system-message-provider.tsx | 49 +++++++++++++++++++ app/root.tsx | 11 +++-- app/routes/app._index/route.tsx | 13 +++-- app/routes/app.post-message/route.tsx | 13 ++++- app/routes/app.setting/route.tsx | 16 ++++-- app/routes/auth.login/route.tsx | 13 ++++- app/routes/auth.register-user/route.tsx | 13 ++++- app/routes/auth.signup/route.tsx | 13 ++++- package-lock.json | 27 +++++++++- package.json | 1 + 11 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 app/contexts/system-message/system-message-context.ts create mode 100644 app/contexts/system-message/system-message-provider.tsx diff --git a/app/contexts/system-message/system-message-context.ts b/app/contexts/system-message/system-message-context.ts new file mode 100644 index 0000000..4c0673b --- /dev/null +++ b/app/contexts/system-message/system-message-context.ts @@ -0,0 +1,9 @@ +import { createContext } from "react"; + +/** + * システムメッセージコンテキスト。 + */ +const SystemMessageContext = createContext({ + showSystemMessage: (status: "success" | "error", message: string) => {} +}); +export default SystemMessageContext; \ No newline at end of file diff --git a/app/contexts/system-message/system-message-provider.tsx b/app/contexts/system-message/system-message-provider.tsx new file mode 100644 index 0000000..fae0150 --- /dev/null +++ b/app/contexts/system-message/system-message-provider.tsx @@ -0,0 +1,49 @@ +import SystemMessageContext from "./system-message-context"; +import { ReactNode } from "react"; +import toast, { Toaster, useToaster } from "react-hot-toast"; + +/** + * システムメッセージプロバイダー。 + * @param children 子要素。 + * @returns システムメッセージプロバイダー。 + */ +const SystemMessageProvider = ({ + children, +}: { + children: ReactNode, +}) => { + const showSystemMessage = (status: "success" | "error", message: string) => { + if (!message) return; + switch (status) { + case "success": + toast.success(message); + break; + case "error": + toast.error(message); + break; + } + }; + + return ( + + {children} + + + ); +}; +export default SystemMessageProvider; \ No newline at end of file diff --git a/app/root.tsx b/app/root.tsx index 698a2b5..97bb176 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -9,6 +9,7 @@ import { Scripts, ScrollRestoration, } from "@remix-run/react"; +import SystemMessageProvider from "./contexts/system-message/system-message-provider"; export const links: LinksFunction = () => [ ...(cssBundleHref ? [ @@ -27,10 +28,12 @@ export default function App() { - - - - + + + + + + ); diff --git a/app/routes/app._index/route.tsx b/app/routes/app._index/route.tsx index 6a14aca..11f6061 100644 --- a/app/routes/app._index/route.tsx +++ b/app/routes/app._index/route.tsx @@ -7,8 +7,9 @@ import { newlyPostedPostCookie } from "../../cookies.server"; import { useFetcher, useLoaderData } from "@remix-run/react"; import PostContent from "../../models/post/post-content"; import InfiniteScroll from "../components/infinite-scroll"; -import { useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { appLoadContext as context } from "../../dependency-injector/get-load-context"; +import SystemMessageContext from "../../contexts/system-message/system-message-context"; import styles from "./route.module.css"; /** @@ -55,9 +56,15 @@ export const loader = async ({ * @returns トップページのインデックス。 */ export default function TopIndex() { - // エラーメッセージを取得する。 + // システムメッセージを取得する。 const loaderData = useLoaderData(); - const errorMessage = "errorMessage" in loaderData ? loaderData.errorMessage : ""; + const loaderErrorMessage = "errorMessage" in loaderData ? loaderData.errorMessage : ""; + + // システムメッセージを表示する。 + const { showSystemMessage } = useContext(SystemMessageContext); + useEffect(() => { + showSystemMessage("error", loaderErrorMessage); + }, [loaderData]); // 最新の投稿を取得する。 const fetcher = useFetcher(); diff --git a/app/routes/app.post-message/route.tsx b/app/routes/app.post-message/route.tsx index daa805a..6e922d8 100644 --- a/app/routes/app.post-message/route.tsx +++ b/app/routes/app.post-message/route.tsx @@ -4,6 +4,8 @@ import { Form, useActionData, useLoaderData } from "@remix-run/react"; import { getSession } from "../../sessions"; import { newlyPostedPostCookie } from "../../cookies.server"; import { appLoadContext as context } from "../../dependency-injector/get-load-context"; +import { useContext, useEffect } from "react"; +import SystemMessageContext from "../../contexts/system-message/system-message-context"; /** * メッセージ投稿ページのメタ情報を設定する。 @@ -88,12 +90,21 @@ export const action = async ({ * @returns メッセージ投稿ページ。 */ export default function PostMessage() { - // エラーメッセージを取得する。 + // システムメッセージを取得する。 const loaderData = useLoaderData(); const loaderErrorMessage = "errorMessage" in loaderData ? loaderData.errorMessage : ""; const actionData = useActionData(); const actionErrorMessage = actionData ? actionData.errorMessage : ""; + // システムメッセージを表示する。 + const { showSystemMessage } = useContext(SystemMessageContext); + useEffect(() => { + showSystemMessage("error", loaderErrorMessage); + }, [loaderData]); + useEffect(() => { + showSystemMessage("error", actionErrorMessage); + }, [actionData]); + // リリース情報を取得する。 const allReleaseInformation = "errorMessage" in loaderData ? [] : loaderData; const getReleaseVersionOptions = () => { diff --git a/app/routes/app.setting/route.tsx b/app/routes/app.setting/route.tsx index 661450d..c74c977 100644 --- a/app/routes/app.setting/route.tsx +++ b/app/routes/app.setting/route.tsx @@ -3,8 +3,9 @@ import { ActionFunctionArgs, LoaderFunctionArgs, MetaFunction, json } from "@rem import { getSession } from "../../sessions"; import { appLoadContext as context } from "../../dependency-injector/get-load-context"; import { Form, useActionData, useLoaderData } from "@remix-run/react"; -import { ChangeEvent, useState } from "react"; +import { ChangeEvent, useContext, useEffect, useState } from "react"; import ErrorDisplay from "../components/error-display"; +import SystemMessageContext from "../../contexts/system-message/system-message-context"; /** * 設定ページのメタ情報を設定する。 @@ -90,13 +91,23 @@ export const action = async ({ * 設定ページ。 */ export default function Setting() { - // エラーメッセージを取得する。 + // システムメッセージを取得する。 const loaderData = useLoaderData(); const loaderErrorMessage = "errorMessage" in loaderData ? loaderData.errorMessage : ""; const actionData = useActionData(); const actionSuccessMessage = actionData && "successMessage" in actionData ? actionData.successMessage : ""; const actionErrorMessage = actionData && "errorMessage" in actionData ? actionData.errorMessage : ""; + // システムメッセージを表示する。 + const { showSystemMessage } = useContext(SystemMessageContext); + useEffect(() => { + showSystemMessage("error", loaderErrorMessage); + }, [loaderData]); + useEffect(() => { + showSystemMessage("success", actionSuccessMessage); + showSystemMessage("error", actionErrorMessage); + }, [actionData]); + // ローダーでエラーが発生した場合、エラーメッセージを表示するコンポーネントを表示する。 if ("errorMessage" in loaderData) { return ( @@ -105,7 +116,6 @@ export default function Setting() { } // ユーザー設定を取得する。 - const settingLoaderData = "errorMessage" in loaderData ? { userSetting: {}, allReleaseInformation: [] } : loaderData; const userSetting = loaderData.userSetting; // リリース情報を全件表示する。 diff --git a/app/routes/auth.login/route.tsx b/app/routes/auth.login/route.tsx index 4b848b5..8d770a0 100644 --- a/app/routes/auth.login/route.tsx +++ b/app/routes/auth.login/route.tsx @@ -3,6 +3,8 @@ import { ActionFunctionArgs, LoaderFunctionArgs, MetaFunction, json, redirect } import { Form, useActionData, useLoaderData } from "@remix-run/react"; import { commitSession, getSession } from "../../sessions"; import { appLoadContext as context } from "../../dependency-injector/get-load-context"; +import { useContext, useEffect } from "react"; +import SystemMessageContext from "../../contexts/system-message/system-message-context"; /** * ログインページのメタ情報を設定する。 @@ -105,12 +107,21 @@ export const action = async ({ * @returns ログインページ。 */ export default function Login() { - // エラーメッセージを取得する。 + // システムメッセージを取得する。 const loaderData = useLoaderData(); const loaderErrorMessage = loaderData && "errorMessage" in loaderData ? loaderData.errorMessage : ""; const actionData = useActionData(); const actionErrorMessage = actionData ? actionData.errorMessage : ""; + // システムメッセージを表示する。 + const { showSystemMessage } = useContext(SystemMessageContext); + useEffect(() => { + showSystemMessage("error", loaderErrorMessage); + }, [loaderData]); + useEffect(() => { + showSystemMessage("error", actionErrorMessage); + }, [actionData]); + return (