From c05bc769e071c05245cd5854912501c96a7a8e7d Mon Sep 17 00:00:00 2001 From: shunsei Date: Tue, 29 Oct 2024 23:23:39 +0900 Subject: [PATCH] Show notification only once (#105) --- frontend/app/routes/_index.tsx | 2 +- frontend/app/routes/auth.login.tsx | 19 ++++---- frontend/app/routes/home._index.tsx | 53 +++++----------------- frontend/app/routes/home.books.$bookId.tsx | 10 ++-- frontend/app/routes/home.tsx | 43 ++++++++++++------ frontend/app/services/session.server.ts | 11 +---- 6 files changed, 58 insertions(+), 80 deletions(-) diff --git a/frontend/app/routes/_index.tsx b/frontend/app/routes/_index.tsx index 2eb33bec..bff60b90 100644 --- a/frontend/app/routes/_index.tsx +++ b/frontend/app/routes/_index.tsx @@ -8,5 +8,5 @@ export const meta: MetaFunction = () => { }; export async function loader() { - return redirect('home'); + return redirect('/home'); } diff --git a/frontend/app/routes/auth.login.tsx b/frontend/app/routes/auth.login.tsx index 62c76216..fe0fdc8d 100644 --- a/frontend/app/routes/auth.login.tsx +++ b/frontend/app/routes/auth.login.tsx @@ -28,7 +28,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { // 未ログインの場合 // エラーメッセージを取得 - const data = { error: session.get('loginError') }; + const data = { error: session.get('error') }; return json(data, { headers: { @@ -51,8 +51,8 @@ export const action = async ({ request }: ActionFunctionArgs) => { if (response.status === 200) { session.set('userId', response.data.id.toString()); session.set('sessionToken', response.data.sessionToken!); - // FIXME: ログアウト時に表示できないのでログイン時も表示しない - // session.flash('loginSuccess', 'ログインに成功しました'); + // FIXME: homeのloaderで読み出してもCookieが削除されない + session.flash('success', 'ログインに成功しました'); return redirect('/home/mypage', { headers: { @@ -65,26 +65,25 @@ export const action = async ({ request }: ActionFunctionArgs) => { switch (response.status) { case 400: // prettier-ignore - session.flash('loginError', 'メールアドレスまたはパスワードが間違っています'); + session.flash('error', 'メールアドレスまたはパスワードが間違っています'); break; case 401: // prettier-ignore - session.flash('loginError', 'メールアドレスまたはパスワードが間違っています'); + session.flash('error', 'メールアドレスまたはパスワードが間違っています'); break; case 404: - session.flash('loginError', 'ユーザーが見つかりません'); + session.flash('error', 'ユーザーが見つかりません'); break; case 500: - session.flash('loginError', 'サーバーエラーが発生しました'); + session.flash('error', 'サーバーエラーが発生しました'); break; default: - session.flash('loginError', 'エラーが発生しました'); + session.flash('error', 'エラーが発生しました'); } - const setCookie = await commitSession(session); return redirect('/auth/login', { headers: { - 'Set-Cookie': setCookie, + 'Set-Cookie': await commitSession(session), }, }); }; diff --git a/frontend/app/routes/home._index.tsx b/frontend/app/routes/home._index.tsx index abdf47be..e69e1fef 100644 --- a/frontend/app/routes/home._index.tsx +++ b/frontend/app/routes/home._index.tsx @@ -8,9 +8,7 @@ import { GetBooksParams } from 'client/client.schemas'; import { useAtom } from 'jotai'; import { useEffect } from 'react'; import BookListComponent from '~/components/books/BookListComponent'; -import { commitSession, getSession } from '~/services/session.server'; import { selectedBooksAtom } from '~/stores/cartAtom'; -import { errorNotification, successNotification } from '~/utils/notification'; interface LoaderData { booksResponse: getBooksResponse; @@ -22,10 +20,6 @@ interface LoaderData { page?: string; limit?: string; }; - flash: { - success?: string; - error?: string; - }; } export const loader = async ({ request }: LoaderFunctionArgs) => { @@ -47,40 +41,22 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { limit: limit, }); - const session = await getSession(request.headers.get('Cookie')); - - // flashメッセージを取得する - const success = session.get('deleteBookSuccess'); - const error = session.get('deleteBookError'); - - return json( - { - booksResponse: response, - condition: { - title: title, - author: auther, - publisher: publisher, - isbn: isbn, - page: page, - limit: limit, - }, - flash: { - success: success, - error: error, - }, - }, - { - headers: { - 'Set-Cookie': await commitSession(session), - }, + return json({ + booksResponse: response, + condition: { + title: title, + author: auther, + publisher: publisher, + isbn: isbn, + page: page, + limit: limit, }, - ); + }); }; const BooKListPage = () => { - const { booksResponse, condition, flash } = useLoaderData(); + const { booksResponse, condition } = useLoaderData(); const { title, author, publisher, isbn, page, limit } = condition; - const { success, error } = flash; const [opened, { open, close }] = useDisclosure(); const navigate = useNavigate(); @@ -96,13 +72,6 @@ const BooKListPage = () => { }); useEffect(() => { - // flashメッセージを表示する - if (success) { - successNotification(success); - } else if (error) { - errorNotification(error); - } - // 選択中の書籍をリセットする setSelectedBook([]); }, []); diff --git a/frontend/app/routes/home.books.$bookId.tsx b/frontend/app/routes/home.books.$bookId.tsx index 4f663837..4bd5385d 100644 --- a/frontend/app/routes/home.books.$bookId.tsx +++ b/frontend/app/routes/home.books.$bookId.tsx @@ -58,7 +58,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { // 未ログインの場合 if (!session.has('userId')) { - session.flash('loginError', 'ログインしてください'); + session.flash('error', 'ログインしてください'); return redirect('/auth/login', { headers: { 'Set-Cookie': await commitSession(session), @@ -80,28 +80,28 @@ export const action = async ({ request }: ActionFunctionArgs) => { }); switch (response.status) { case 204: - session.flash('deleteBookSuccess', '削除しました'); + session.flash('success', '削除しました'); return redirect('/home', { headers: { 'Set-Cookie': await commitSession(session), }, }); case 401: - session.flash('loginError', 'ログインしてください'); + session.flash('error', 'ログインしてください'); return redirect('/auth/login', { headers: { 'Set-Cookie': await commitSession(session), }, }); case 404: - session.flash('deleteBookError', '書籍が見つかりませんでした'); + session.flash('error', '書籍が見つかりませんでした'); return redirect('/home', { headers: { 'Set-Cookie': await commitSession(session), }, }); case 500: - session.flash('deleteBookError', 'サーバーエラーが発生しました'); + session.flash('error', 'サーバーエラーが発生しました'); return json( { method: 'DELETE', status: 500 }, { diff --git a/frontend/app/routes/home.tsx b/frontend/app/routes/home.tsx index 07ee8677..469f90bd 100644 --- a/frontend/app/routes/home.tsx +++ b/frontend/app/routes/home.tsx @@ -10,25 +10,28 @@ import { getUser, logout } from 'client/client'; import { useAtom } from 'jotai'; import { useEffect } from 'react'; import HeaderComponent from '~/components/header/HeaderComponent'; -import { - commitSession, - destroySession, - getSession, -} from '~/services/session.server'; +import { commitSession, getSession } from '~/services/session.server'; import { userAtom } from '~/stores/userAtom'; +import { errorNotification, successNotification } from '~/utils/notification'; interface LoaderData { userId?: string; + success?: string; + error?: string; } export const loader = async ({ request }: LoaderFunctionArgs) => { const session = await getSession(request.headers.get('Cookie')); const userId = session.get('userId'); + const success = session.get('success'); + const error = session.get('error'); return json( { userId: userId, + success: success, + error: error, }, { headers: { @@ -51,24 +54,26 @@ export const action = async ({ request }: ActionFunctionArgs) => { if (response.status === 204) { session.unset('userId'); session.unset('sessionToken'); - // FIXME: loaderで読み出しても削除されない - // session.flash('logoutSuccess', 'ログアウトに成功しました'); + session.flash('success', 'ログアウトに成功しました'); return redirect('/home', { headers: { - 'Set-Cookie': await destroySession(session), + 'Set-Cookie': await commitSession(session), }, }); } else { - // FIXME: loaderで読み出しても削除されない - // session.flash('logoutError', 'ログアウトに失敗しました'); + session.flash('error', 'ログアウトに失敗しました'); - return redirect('/home'); + return redirect('/home', { + headers: { + 'Set-Cookie': await commitSession(session), + }, + }); } }; const Home = () => { - const { userId } = useLoaderData(); + const { userId, success, error } = useLoaderData(); const [user, setUser] = useAtom(userAtom); const navigation = useNavigation(); @@ -90,7 +95,19 @@ const Home = () => { setUser(undefined); } } - }, [navigation.state]); + }, [userId]); + + useEffect(() => { + if (success) { + successNotification(success); + } + }, [success]); + + useEffect(() => { + if (error) { + errorNotification(error); + } + }, [error]); return ( diff --git a/frontend/app/services/session.server.ts b/frontend/app/services/session.server.ts index 72150613..392baae1 100644 --- a/frontend/app/services/session.server.ts +++ b/frontend/app/services/session.server.ts @@ -6,15 +6,8 @@ interface SessionData { } interface SessionFlashData { - // ログイン - // loginSuccess: string; - loginError: string; - // ログアウト - // logoutSuccess: string; - // logoutError: string; - // 書籍の削除 - deleteBookSuccess: string; - deleteBookError: string; + success?: string; + error?: string; } const { getSession, commitSession, destroySession } =