
진행하고 있는 프로젝트에 비슷한 스타일의 드롭다운 ui가 있어서 공통 컴포넌트로 따로 구현 해 놓으면 편할 것 같다는 생각이 들었다.
드롭다운 라이브러리가 있긴 하지만( e.g. react-dropdown ) 구현하는 방법이 그렇게 복잡하지 않은 것 같아서 직접 구현해보려고 한다.
공통 컴포넌트로써 필수적으로 있어야 할 기능을 추려보자면
이 두 가지 인 것 같다.
//000page.js
const SORT_OPTION_DATA = ["최근추가", "자주사용", "제목순"];
const CATEGORY_OPTION_DATA = ["전체", "내 카드", "참조 카드"];
...
funtion 000page () {
const handleSortChange = (value) => console.log("sort:", value);
const handleCategoryChange = (value) => console.log("category:", value);
return <>
...
<Dropdown options={SORT_OPTION_DATA} onChange={handleSortChange} />
<Dropdown options={CATEGORY_OPTION_DATA} onChange={handleCategoryChange} />
...
}
export default 000page;
handleSortChange나 handleCategoryChange에는 사용자가 선택한 데이터 값에 따른 동작을 추가로 작성하면 된다.
//DropDown.js
function Dropdown({ options, onChange }) {
const [currentValue, setCurrentValue] = useState(options[0]);
const [showOptions, setShowOptions] = useState(false);
const dropdownRef = useRef(null);
const handleSelectValue = (value) => {
setCurrentValue(value);
onChange?.(value);
};
//사용자가 dropdown list를 연 상태에서 다른 곳을 클릭할 시 dropdown list를 닫음
useEffect(() => {
const handleClickOutside = (e) => {
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
setShowOptions(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
return (
<div
ref={dropdownRef}
onClick={() => setShowOptions((prev) => !prev)}
>
<label>{currentValue}</label>
{showOptions && (
<ul>
{options.map((option, index) => (
<li
key={option + index}
value={option}
onClick={() => handleSelectValue(option)}
>
{option}
<div>{currentValue === option && "✔"} </div>
</li>
))}
</ul>
)}
</div>
);
}
export default Dropdown;

구현 완료한 화면이다.