검색창에 자동완성 기능을 추가하던 중, 입력 후 자동완성 리스트가 계속 열린 상태로 유지되는 문제가 있었습니다.
사용자가 입력창 외부를 클릭하면 자동완성 리스트가 자연스럽게 닫혀야 하기 때문에 외부 클릭을 감지하는 로직이 필요했습니다.
외부 클릭 감지를 구현하기 위해서는 ref
와 document.addEventListener
가 필요합니다.
ref
는 특정 DOM 요소에 직접 접근하기 위해 사용되며, document.addEventListener
는 문서 전체에서 발생하는 클릭 이벤트를 감지하기 위해 사용됩니다.
const [isOpen, setIsOpen] = useState(false);
const wrapperRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
// ref로 참조한 요소가 존재하고,
// 클릭된 요소(e.target)가 그 요소 내부(wrapperRef.current)에 포함되어 있지 않은 경우
if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {
setIsOpen(false); // 외부 클릭 시 자동완성 닫기
}
};
// 문서 전체에서 마우스 클릭이 발생했을 때 handleClickOutside 함수가 실행되도록 이벤트를 등록
document.addEventListener('mousedown', handleClickOutside);
return () => {
// 등록한 mousedown 이벤트 리스너를 제거해, 컴포넌트가 사라질 때 불필요한 이벤트 호출을 방지
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
위 코드는 ref
로 감싼 컴포넌트 외부를 클릭했을 때 자동완성 UI를 닫는 로직입니다.
ref
를 통해 기준 영역을 지정하고,document
의 전역 클릭 이벤트를 통해 외부 클릭 여부를 감지하며,그리고 input
에 포커스가 될 때 setIsOpen(true)
를 호출하면, 자동완성 UI를 입력 전에 미리 열어줄 수도 있습니다.