Skip to content

Commit

Permalink
システムメッセージをトーストで表示できるようにした。
Browse files Browse the repository at this point in the history
  • Loading branch information
eigoninaritai-naokichi committed Feb 18, 2024
1 parent 7967a4b commit d71e8c2
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 16 deletions.
9 changes: 9 additions & 0 deletions app/contexts/system-message/system-message-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createContext } from "react";

/**
* システムメッセージコンテキスト。
*/
const SystemMessageContext = createContext({
showSystemMessage: (status: "success" | "error", message: string) => {}
});
export default SystemMessageContext;
49 changes: 49 additions & 0 deletions app/contexts/system-message/system-message-provider.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<SystemMessageContext.Provider value={{ showSystemMessage }}>
{children}
<Toaster
position="bottom-right"
toastOptions={{
className: "",
style: {
background: "#363636",
color: "#fff",
},
success: {
duration: 3000,
},
error: {
duration: 4000,
},
}}
/>
</SystemMessageContext.Provider>
);
};
export default SystemMessageProvider;
11 changes: 7 additions & 4 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 ? [
Expand All @@ -27,10 +28,12 @@ export default function App() {
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
<SystemMessageProvider>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</SystemMessageProvider>
</body>
</html>
);
Expand Down
13 changes: 10 additions & 3 deletions app/routes/app._index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
Expand Down Expand Up @@ -55,9 +56,15 @@ export const loader = async ({
* @returns トップページのインデックス。
*/
export default function TopIndex() {
// エラーメッセージを取得する
// システムメッセージを取得する
const loaderData = useLoaderData<typeof loader>();
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<typeof loader>();
Expand Down
13 changes: 12 additions & 1 deletion app/routes/app.post-message/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
* メッセージ投稿ページのメタ情報を設定する。
Expand Down Expand Up @@ -88,12 +90,21 @@ export const action = async ({
* @returns メッセージ投稿ページ。
*/
export default function PostMessage() {
// エラーメッセージを取得する
// システムメッセージを取得する
const loaderData = useLoaderData<typeof loader>();
const loaderErrorMessage = "errorMessage" in loaderData ? loaderData.errorMessage : "";
const actionData = useActionData<typeof action>();
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 = () => {
Expand Down
16 changes: 13 additions & 3 deletions app/routes/app.setting/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
* 設定ページのメタ情報を設定する。
Expand Down Expand Up @@ -90,13 +91,23 @@ export const action = async ({
* 設定ページ。
*/
export default function Setting() {
// エラーメッセージを取得する
// システムメッセージを取得する
const loaderData = useLoaderData<typeof loader>();
const loaderErrorMessage = "errorMessage" in loaderData ? loaderData.errorMessage : "";
const actionData = useActionData<typeof action>();
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 (
Expand All @@ -105,7 +116,6 @@ export default function Setting() {
}

// ユーザー設定を取得する。
const settingLoaderData = "errorMessage" in loaderData ? { userSetting: {}, allReleaseInformation: [] } : loaderData;
const userSetting = loaderData.userSetting;

// リリース情報を全件表示する。
Expand Down
13 changes: 12 additions & 1 deletion app/routes/auth.login/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
* ログインページのメタ情報を設定する。
Expand Down Expand Up @@ -105,12 +107,21 @@ export const action = async ({
* @returns ログインページ。
*/
export default function Login() {
// エラーメッセージを取得する
// システムメッセージを取得する
const loaderData = useLoaderData<typeof loader>();
const loaderErrorMessage = loaderData && "errorMessage" in loaderData ? loaderData.errorMessage : "";
const actionData = useActionData<typeof action>();
const actionErrorMessage = actionData ? actionData.errorMessage : "";

// システムメッセージを表示する。
const { showSystemMessage } = useContext(SystemMessageContext);
useEffect(() => {
showSystemMessage("error", loaderErrorMessage);
}, [loaderData]);
useEffect(() => {
showSystemMessage("error", actionErrorMessage);
}, [actionData]);

return (
<Form method="post">
<label>
Expand Down
13 changes: 12 additions & 1 deletion app/routes/auth.register-user/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ActionFunctionArgs, LoaderFunctionArgs, MetaFunction, json, redirect }
import { Form, useActionData, useLoaderData } from "@remix-run/react";
import { commitSession, destroySession, 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";

/**
* ログインページのメタ情報を設定する。
Expand Down Expand Up @@ -107,12 +109,21 @@ export const action = async ({
* @returns ユーザー登録ページ。
*/
export default function RegisterUser() {
// エラーメッセージを取得する
// システムメッセージを取得する
const loaderData = useLoaderData<typeof loader>();
const loaderErrorMessage = "errorMessage" in loaderData ? loaderData.errorMessage : "";
const actionData = useActionData<typeof action>();
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 = () => {
Expand Down
13 changes: 12 additions & 1 deletion app/routes/auth.signup/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
* サインアップページのメタ情報を設定する。
Expand Down Expand Up @@ -89,12 +91,21 @@ export const action = async ({
* @returns サインアップページ。
*/
export default function Signup() {
// エラーメッセージを取得する
// システムメッセージを取得する
const loaderData = useLoaderData<typeof loader>();
const loaderErrorMessage = loaderData && "errorMessage" in loaderData ? loaderData.errorMessage : "";
const actionData = useActionData<typeof action>();
const actionErrorMessage = actionData ? actionData.errorMessage : "";

// システムメッセージを表示する。
const { showSystemMessage } = useContext(SystemMessageContext);
useEffect(() => {
showSystemMessage("error", actionErrorMessage);
}, [loaderData]);
useEffect(() => {
showSystemMessage("error", actionErrorMessage);
}, [actionData]);

return (
<Form method="post">
<label>
Expand Down
27 changes: 25 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"pg": "^8.11.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"source-map-support": "^0.5.21"
},
"devDependencies": {
Expand Down

0 comments on commit d71e8c2

Please sign in to comment.