diff --git a/frontend/src/component/common/dropdown/Dropdown.tsx b/frontend/src/component/common/dropdown/Dropdown.tsx index 0d8e1acf..d9c194c3 100644 --- a/frontend/src/component/common/dropdown/Dropdown.tsx +++ b/frontend/src/component/common/dropdown/Dropdown.tsx @@ -1,8 +1,9 @@ -import { ReactNode } from 'react'; +import { ReactNode, useMemo } from 'react'; +import { v4 as uuidv4 } from 'uuid'; import { DropdownTrigger } from '@/component/common/dropdown/DropdownTrigger.tsx'; import { DropdownItem } from '@/component/common/dropdown/DropdownItem.tsx'; import { DropdownMenu } from '@/component/common/dropdown/DropdownMenu.tsx'; -import { ToggleProvider } from '@/component/common/dropdown/DropdownContext.tsx'; +import { DropdownInstanceContext } from '@/context/DropdownInstanceContext'; interface IDropdownProps { /** 드롭다운 컴포넌트 내부에 들어갈 컨텐츠 */ @@ -34,10 +35,12 @@ interface IDropdownProps { */ export const Dropdown = (props: IDropdownProps) => { + const id = useMemo(() => uuidv4(), []); // 각 Dropdown 인스턴스에 고유 ID 생성 + return ( - + + + ); }; diff --git a/frontend/src/component/common/dropdown/DropdownContext.tsx b/frontend/src/component/common/dropdown/DropdownContext.tsx deleted file mode 100644 index 61b865ac..00000000 --- a/frontend/src/component/common/dropdown/DropdownContext.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { createContext, ReactNode, useMemo, useState } from 'react'; - -export interface IToggleContext { - isOpen: boolean; - toggle: () => void; -} - -interface IToggleProviderProps { - children: ReactNode; -} - -export const ToggleContext = createContext({ - isOpen: false, - toggle: () => {}, -}); - -export const ToggleProvider = (props: IToggleProviderProps) => { - const [isOpen, setIsOpen] = useState(false); - const toggle = () => setIsOpen(prevIsOpen => !prevIsOpen); - const toggleContextValue = useMemo(() => ({ isOpen, toggle }), [isOpen]); - - return ( - {props.children} - ); -}; diff --git a/frontend/src/component/common/dropdown/DropdownMenu.tsx b/frontend/src/component/common/dropdown/DropdownMenu.tsx index c49eab34..189cd792 100644 --- a/frontend/src/component/common/dropdown/DropdownMenu.tsx +++ b/frontend/src/component/common/dropdown/DropdownMenu.tsx @@ -1,6 +1,7 @@ import { ReactNode, useContext, useRef, useEffect } from 'react'; import classNames from 'classnames'; -import { ToggleContext } from '@/component/common/dropdown/DropdownContext'; +import { ToggleContext } from '@/context/DropdownContext.tsx'; +import { DropdownInstanceContext } from '@/context/DropdownInstanceContext'; interface IDropdownMenuProps { /** 드롭다운 메뉴가 열려있는지 여부 */ @@ -27,7 +28,9 @@ interface IDropdownMenuProps { */ export const DropdownMenu = (props: IDropdownMenuProps) => { - const { isOpen, toggle } = useContext(ToggleContext); + const { openDropdownId, setOpenDropdownId } = useContext(ToggleContext); + const dropdownId = useContext(DropdownInstanceContext); + const isOpen = openDropdownId === dropdownId; const ref = useRef(null); const handleOutSideClick = (event: MouseEvent) => { @@ -43,23 +46,26 @@ export const DropdownMenu = (props: IDropdownMenuProps) => { !ref.current.contains(target) && target.dataset.component !== 'DropdownTrigger' ) { - toggle(); + setOpenDropdownId(null); // 외부 클릭 시 드롭다운 닫기 } }; useEffect(() => { - document.addEventListener('click', handleOutSideClick); + if (isOpen) { + document.addEventListener('click', handleOutSideClick); + } else { + document.removeEventListener('click', handleOutSideClick); + } return () => { document.removeEventListener('click', handleOutSideClick); }; - }, []); + }, [isOpen]); return ( isOpen && (