diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts index 12350e798..b5f94df84 100644 --- a/client/src/apis/useFetch.ts +++ b/client/src/apis/useFetch.ts @@ -1,9 +1,8 @@ import {useState} from 'react'; import {NavigateFunction, useNavigate} from 'react-router-dom'; -import useEventId from '@hooks/useEventId'; - import sendLogToSentry from '@utils/sendLogToSentry'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; import {UNKNOWN_ERROR} from '@constants/errorMessage'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -21,7 +20,7 @@ export const useFetch = () => { const {setError, clearError} = useError(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const fetch = async ({queryFunction, onSuccess, onError}: FetchProps): Promise => { setLoading(true); diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index ab9d5fcc0..4d910ac99 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -2,6 +2,7 @@ const REGEXP = { eventPassword: /^[0-9]*$/, memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, + eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, }; export default REGEXP; diff --git a/client/src/hooks/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction.tsx index 0a2c0ac95..1883929f2 100644 --- a/client/src/hooks/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction.tsx @@ -5,18 +5,19 @@ import {useState} from 'react'; import {useToast} from '@components/Toast/ToastProvider'; import {requestDeleteMemberAction} from '@apis/request/member'; -import useEventId from '@hooks/useEventId'; import {useStepList} from '@hooks/useStepList'; import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + const useDeleteMemberAction = ( memberActionList: MemberAction[], setIsBottomSheetOpened: React.Dispatch>, ) => { const {stepList, refreshStepList} = useStepList(); const [aliveActionList, setAliveActionList] = useState(memberActionList); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {showToast} = useToast(); const {fetch} = useFetch(); diff --git a/client/src/hooks/useEventId.tsx b/client/src/hooks/useEventId.tsx deleted file mode 100644 index ca3775f8e..000000000 --- a/client/src/hooks/useEventId.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import {useEffect, useState} from 'react'; -import {useLocation} from 'react-router-dom'; - -const useEventId = () => { - const [eventId, setEventId] = useState(''); - const location = useLocation(); - - const extractIdFromUrl = (url: string) => { - const regex = /\/event\/([a-zA-Z0-9-]+)\//; - const match = url.match(regex); - return match ? match[1] : null; - }; - - const curEventId = extractIdFromUrl(location.pathname) ?? ''; - - useEffect(() => { - setEventId(curEventId); - }, []); - - return { - eventId, - }; -}; - -export default useEventId; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 445172f21..9cb399ef8 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -5,12 +5,13 @@ import {useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; import {requestDeleteBillAction, requestPutBillAction} from '@apis/request/bill'; -import useEventId from '@hooks/useEventId'; import {useStepList} from '@hooks/useStepList'; import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + import ERROR_MESSAGE from '@constants/errorMessage'; const usePutAndDeleteBillAction = ( @@ -18,7 +19,7 @@ const usePutAndDeleteBillAction = ( validateFunc: (inputPair: Bill) => ValidateResult, onClose: () => void, ) => { - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {refreshStepList} = useStepList(); const {fetch} = useFetch(); diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index d8acfb00c..fb9b547a6 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -4,7 +4,7 @@ import {requestGetCurrentInMemberList} from '@apis/request/member'; import {useFetch} from '@apis/useFetch'; -import useEventId from './useEventId'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; export type ReturnUseSearchInMemberList = { currentInputIndex: number; @@ -17,7 +17,7 @@ export type ReturnUseSearchInMemberList = { const useSearchInMemberList = ( setInputValueTargetIndex: (index: number, value: string) => void, ): ReturnUseSearchInMemberList => { - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {fetch} = useFetch(); const [currentInputIndex, setCurrentInputIndex] = useState(-1); @@ -29,15 +29,13 @@ const useSearchInMemberList = ( const [filteredInMemberList, setFilteredInMemberList] = useState>([]); useEffect(() => { - if (eventId === '') return; - const getCurrentInMembers = async () => { const currentInMemberListFromServer = await fetch({queryFunction: () => requestGetCurrentInMemberList(eventId)}); setCurrentInMemberList(currentInMemberListFromServer.members); }; getCurrentInMembers(); - }, [eventId]); + }, []); const filterMatchItems = (keyword: string) => { if (keyword.trim() === '') return []; diff --git a/client/src/hooks/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList.tsx index 7dca34b68..ccbc5358f 100644 --- a/client/src/hooks/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList.tsx @@ -4,10 +4,10 @@ import {useEffect, useState} from 'react'; import {requestGetMemberReportList} from '@apis/request/report'; -import useEventId from '@hooks/useEventId'; - import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + type UseSearchMemberReportListParams = { name: string; }; @@ -15,21 +15,20 @@ type UseSearchMemberReportListParams = { const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { const [memberReportList, setMemberReportList] = useState([]); const [memberReportSearchList, setMemberReportSearchList] = useState([]); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {fetch} = useFetch(); useEffect(() => { const fetchMemberReportList = async () => { // TODO: (@weadie) cors 고쳐지면 주석 풀게요. // TODO: (@weadie) eventId에 의존하는 두 개의 훅에 대한 리펙토링 필요 - if (eventId === '') return; const memberReportListData = await fetch({queryFunction: () => requestGetMemberReportList({eventId})}); setMemberReportList(memberReportListData); }; fetchMemberReportList(); - }, [eventId]); + }, []); // TODO: (@weadie) 글자가 완성될 때마다 아래 로직이 실행되어야 합니다. useEffect(() => { diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index c0c14c13a..44066dbf6 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -6,8 +6,8 @@ import {MemberChange, requestDeleteAllMemberList, requestPutAllMemberList} from import {useFetch} from '@apis/useFetch'; import isArraysEqual from '@utils/isArraysEqual'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; -import useEventId from './useEventId'; import {useStepList} from './useStepList'; interface UseSetAllMemberListProps { @@ -29,7 +29,7 @@ const useSetAllMemberList = ({ const [deleteMemberList, setDeleteMemberList] = useState([]); const {refreshStepList} = useStepList(); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {fetch} = useFetch(); useEffect(() => { diff --git a/client/src/hooks/useStepList.tsx b/client/src/hooks/useStepList.tsx index d0f31abaa..4898925a6 100644 --- a/client/src/hooks/useStepList.tsx +++ b/client/src/hooks/useStepList.tsx @@ -6,10 +6,10 @@ import {requestPostBillList} from '@apis/request/bill'; import {requestGetAllMemberList, requestPostMemberList} from '@apis/request/member'; import {requestGetStepList} from '@apis/request/stepList'; -import useEventId from '@hooks/useEventId'; - import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + interface StepListContextProps { stepList: (BillStep | MemberStep)[]; allMemberList: string[]; @@ -25,16 +25,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const {fetch} = useFetch(); const [stepList, setStepList] = useState<(BillStep | MemberStep)[]>([]); const [allMemberList, setAllMemberList] = useState([]); - - const {eventId} = useEventId(); - - useEffect(() => { - if (eventId === '') return; - - refreshStepList(); - - // TODO: (@weadie) useEffect를 꼭 써야하는가? - }, [eventId]); + const eventId = getEventIdByUrl(); const refreshStepList = async () => { const stepList = await fetch({queryFunction: () => requestGetStepList({eventId})}); @@ -43,6 +34,10 @@ const StepListProvider = ({children}: PropsWithChildren) => { setStepList(stepList); }; + useEffect(() => { + refreshStepList(); + }, []); + const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { try { await fetch({queryFunction: () => requestPostMemberList({eventId, type, memberNameList})}); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index d11409a33..a1ea053d9 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,17 +1,13 @@ import {useEffect, useState} from 'react'; import {Title, FixedButton, ListButton} from 'haengdong-design'; -import {useNavigate, useOutletContext} from 'react-router-dom'; +import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; -import {requestGetEventName} from '@apis/request/event'; import {ModalBasedOnMemberCount} from '@components/Modal/index'; import {useStepList} from '@hooks/useStepList'; -import useEventId from '@hooks/useEventId'; import useAuth from '@hooks/useAuth'; -import {ROUTER_URLS} from '@constants/routerUrls'; - import {EventPageContextProps} from '../EventPageLayout'; import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; @@ -24,21 +20,14 @@ const AdminPage = () => { const {getTotalPrice, allMemberList} = useStepList(); const {postAuthentication} = useAuth(); - const navigate = useNavigate(); useEffect(() => { - if (eventId === '') return; - const postAuth = async () => { - try { - await postAuthentication({eventId: eventId}); - } catch (error) { - navigate(`${ROUTER_URLS.event}/${eventId}/login`); - } + await postAuthentication({eventId: eventId}); }; postAuth(); - }, [eventId]); + }, []); const handleOpenAllMemberListButton = () => { setIsOpenFixedBottomBottomSheet(prev => !prev); diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index fda0d841c..d9c8c2128 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,13 +1,14 @@ import {useState} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back, Switch} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Switch} from 'haengdong-design'; import validateEventPassword from '@utils/validate/validateEventPassword'; -import useEventId from '@hooks/useEventId'; import useAuth from '@hooks/useAuth'; import useNavSwitch from '@hooks/useNavSwitch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -17,7 +18,7 @@ const EventLoginPage = () => { const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {postLogin} = useAuth(); const submitPassword = async (event: React.FormEvent) => { diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index bb6d0a15f..13a6aa67a 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,5 +1,5 @@ import {MainLayout, TopNav, Switch, Button, Flex} from 'haengdong-design'; -import {Outlet, useLocation, useMatch, useNavigate} from 'react-router-dom'; +import {Outlet, useMatch} from 'react-router-dom'; import {useEffect, useState} from 'react'; import CopyToClipboard from 'react-copy-to-clipboard'; @@ -8,7 +8,8 @@ import {requestGetEventName} from '@apis/request/event'; import useNavSwitch from '@hooks/useNavSwitch'; import StepListProvider from '@hooks/useStepList'; -import useEventId from '@hooks/useEventId'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -21,8 +22,8 @@ export type EventPageContextProps = { const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); - const {eventId} = useEventId(); const [eventName, setEventName] = useState(''); + const eventId = getEventIdByUrl(); useEffect(() => { const getEventName = async () => { @@ -32,7 +33,7 @@ const EventPageLayout = () => { }; getEventName(); - }, [eventId]); + }, []); const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; diff --git a/client/src/utils/getEventIdByUrl.ts b/client/src/utils/getEventIdByUrl.ts new file mode 100644 index 000000000..f52885215 --- /dev/null +++ b/client/src/utils/getEventIdByUrl.ts @@ -0,0 +1,13 @@ +import REGEXP from '@constants/regExp'; + +const extractEventIdFromUrl = (url: string) => { + const regex = REGEXP.eventUrl; + const match = url.match(regex); + return match ? match[1] : null; +}; + +const getEventIdByUrl = () => { + return extractEventIdFromUrl(window.location.pathname) || ''; +}; + +export default getEventIdByUrl;