From 7fab2d7a7cb46204aaf17510a75c907cf6010621 Mon Sep 17 00:00:00 2001 From: hamo-o Date: Sun, 22 Jun 2025 15:25:41 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20gitignore=20env=EB=A1=9C=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=ED=95=98=EB=8A=94=20=EB=AA=A8=EB=93=A0=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/.gitignore b/frontend/.gitignore index f0abd802..348bb0b4 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -11,6 +11,7 @@ node_modules dist dist-ssr *.local +.env* # Editor directories and files .vscode/* From 54597fdb4f104f812be580f76cbe86cec3ca19ee Mon Sep 17 00:00:00 2001 From: hamo-o Date: Sun, 22 Jun 2025 15:26:02 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20useEffect=EB=A5=BC=20=ED=95=9C?= =?UTF-8?q?=EB=B2=88=EB=A7=8C=20=ED=98=B8=EC=B6=9C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=ED=9B=85=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apps/client/src/hooks/useEffectOnce.ts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 frontend/apps/client/src/hooks/useEffectOnce.ts diff --git a/frontend/apps/client/src/hooks/useEffectOnce.ts b/frontend/apps/client/src/hooks/useEffectOnce.ts new file mode 100644 index 00000000..6ec28e38 --- /dev/null +++ b/frontend/apps/client/src/hooks/useEffectOnce.ts @@ -0,0 +1,29 @@ +import { useEffect, useRef } from 'react'; + +interface UseEffectOnceOptions { + condition?: boolean; + callback: () => void; +} + +/** + * + * @param options + * @param options.condition - 콜백을 실행할 조건 (기본값: true) + * @param options.callback - 한 번만 실행할 콜백 함수. useCallback을 사용하여 메모이제이션하는 것이 좋습니다. + */ +export const useEffectOnce = ({ condition = true, callback }: UseEffectOnceOptions) => { + const isCalled = useRef(false); + + useEffect(() => { + if (condition && !isCalled.current) { + callback(); + isCalled.current = true; + } + + return () => { + if (!isCalled.current) { + isCalled.current = true; + } + }; + }, [condition, callback]); +}; \ No newline at end of file From 750abb84adc2c930c044aa69ff17957f8ec8a1f0 Mon Sep 17 00:00:00 2001 From: hamo-o Date: Sun, 22 Jun 2025 15:39:10 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EA=B6=8C=ED=95=9C=EC=8A=B5?= =?UTF-8?q?=EB=93=9D=20=EB=A1=9C=EC=A7=81=EC=97=90=20useEffectOnce=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/routes/oauth.redirect/calendar/index.tsx | 7 +++++-- .../src/routes/oauth.redirect/login/index.tsx | 16 ++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx b/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx index cd68906c..b55a9d54 100644 --- a/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx +++ b/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx @@ -1,19 +1,22 @@ import { useQueryClient } from '@tanstack/react-query'; import { createFileRoute, useNavigate } from '@tanstack/react-router'; -import { useEffect } from 'react'; +import { useCallback } from 'react'; import { calendarKeys } from '@/features/my-calendar/api/keys'; +import { useEffectOnce } from '@/hooks/useEffectOnce'; const Redirect = () => { const queryClient = useQueryClient(); const navigate = useNavigate(); - useEffect(() => { + const clearCalendarCache = useCallback(() => { (async () => { await queryClient.invalidateQueries({ queryKey: calendarKeys.all }); navigate({ to: '/my-calendar' }); })(); }, [queryClient, navigate]); + + useEffectOnce({ callback: clearCalendarCache }); return null; }; diff --git a/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx b/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx index 8e3a91b9..bcbc6e36 100644 --- a/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx +++ b/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx @@ -1,7 +1,8 @@ import { createFileRoute, useSearch } from '@tanstack/react-router'; -import { useEffect } from 'react'; +import { useCallback } from 'react'; import { useJWTMutation } from '@/features/login/api/mutations'; +import { useEffectOnce } from '@/hooks/useEffectOnce'; import { getLastRoutePath } from '@/utils/route'; const Redirect = () => { @@ -10,11 +11,14 @@ const Redirect = () => { const params: { code: string } = useSearch({ from: '/oauth/redirect/login/' }); const { code } = params; - useEffect(() => { - if (code) { - loginMutate({ code, lastPath }); - } - }, [code, loginMutate, lastPath]); + const loginCache = useCallback(() => { + loginMutate({ code, lastPath }); + }, [loginMutate, code, lastPath]); + + useEffectOnce({ + condition: Boolean(code), + callback: loginCache, + }); return null; }; From eb42a18c5ca00214d9753525af262abc9d6bc829 Mon Sep 17 00:00:00 2001 From: hamo-o Date: Mon, 23 Jun 2025 09:20:14 +0900 Subject: [PATCH 4/5] =?UTF-8?q?chore:=20useEffectOnce=20=ED=9B=85=20core?= =?UTF-8?q?=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apps/client/src/routes/oauth.redirect/calendar/index.tsx | 2 +- frontend/apps/client/src/routes/oauth.redirect/login/index.tsx | 2 +- frontend/packages/core/src/hooks/index.ts | 1 + .../{apps/client => packages/core}/src/hooks/useEffectOnce.ts | 0 4 files changed, 3 insertions(+), 2 deletions(-) rename frontend/{apps/client => packages/core}/src/hooks/useEffectOnce.ts (100%) diff --git a/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx b/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx index b55a9d54..8d3cb75c 100644 --- a/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx +++ b/frontend/apps/client/src/routes/oauth.redirect/calendar/index.tsx @@ -1,9 +1,9 @@ +import { useEffectOnce } from '@endolphin/core/hooks'; import { useQueryClient } from '@tanstack/react-query'; import { createFileRoute, useNavigate } from '@tanstack/react-router'; import { useCallback } from 'react'; import { calendarKeys } from '@/features/my-calendar/api/keys'; -import { useEffectOnce } from '@/hooks/useEffectOnce'; const Redirect = () => { const queryClient = useQueryClient(); diff --git a/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx b/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx index bcbc6e36..70eccb09 100644 --- a/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx +++ b/frontend/apps/client/src/routes/oauth.redirect/login/index.tsx @@ -1,8 +1,8 @@ +import { useEffectOnce } from '@endolphin/core/hooks'; import { createFileRoute, useSearch } from '@tanstack/react-router'; import { useCallback } from 'react'; import { useJWTMutation } from '@/features/login/api/mutations'; -import { useEffectOnce } from '@/hooks/useEffectOnce'; import { getLastRoutePath } from '@/utils/route'; const Redirect = () => { diff --git a/frontend/packages/core/src/hooks/index.ts b/frontend/packages/core/src/hooks/index.ts index f9880f43..718c9aaa 100644 --- a/frontend/packages/core/src/hooks/index.ts +++ b/frontend/packages/core/src/hooks/index.ts @@ -1,3 +1,4 @@ export * from './useClickOutside'; +export * from './useEffectOnce'; export * from './useSafeContext'; export * from './useSelectTime'; \ No newline at end of file diff --git a/frontend/apps/client/src/hooks/useEffectOnce.ts b/frontend/packages/core/src/hooks/useEffectOnce.ts similarity index 100% rename from frontend/apps/client/src/hooks/useEffectOnce.ts rename to frontend/packages/core/src/hooks/useEffectOnce.ts From fc020ce5497dbe59e727bf9e0589926d7036f433 Mon Sep 17 00:00:00 2001 From: hamo-o Date: Mon, 23 Jun 2025 09:37:53 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/packages/core/src/hooks/useEffectOnce.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/packages/core/src/hooks/useEffectOnce.ts b/frontend/packages/core/src/hooks/useEffectOnce.ts index 6ec28e38..8a0f28c9 100644 --- a/frontend/packages/core/src/hooks/useEffectOnce.ts +++ b/frontend/packages/core/src/hooks/useEffectOnce.ts @@ -17,7 +17,6 @@ export const useEffectOnce = ({ condition = true, callback }: UseEffectOnceOptio useEffect(() => { if (condition && !isCalled.current) { callback(); - isCalled.current = true; } return () => {