ABOUT ME

-

  • [ Vite + React ] 사용자 팝업 만들기
    Front/React 2024. 10. 13. 17:15
    반응형

    구글처럼 상단에 사용자 아이콘을 누르면 바로 아래에 팝업이 나오게 처리


    UserPopup Component

    우선 user icon을 추가하고 open과 onClose함수를 생성

    const [isUserPopup, setIsUserPopup] = useState(false)
    const handleUserPopup = () => {
            setIsUserPopup(!isUserPopup);
    }
    
    return (
            <>
                <div className="user-icon-wrapper">
                	<div onClick={handleUserPopup} className='user-icon'>
                   	 	<User fill='#333333'/>
                	</div>
                <UserPopupComponent isOpen={isUserPopup} onClose={handleUserPopup}/>
                </div>
            </>
        )

     

    import './UserPopupComponent.scss';
    
    const UserPopupComponent = ({ isOpen, onClose }) => {
        return (
            <>
                {isOpen && (
                    <div id="user-popup-container">
                        로그인 유저 이메일 정보
                    </div>
                )}
            </>
        );
    });
    
    export default UserPopupComponent;

     

    이러면 아이콘을 클릭시 팝업이 나오게 되는데

    아이콘을 누르면 그 아래에 팝업이 나오게 처리하고자 css를 활용하여 위치를 조정

     

    아이콘과 팝업컴포넌트들 div로 감싸주어

    position: relative와 display-inline-block을 주어 상대위치를 설정

    .user-icon-wrapper {
      display: inline-block;
      position: relative;
    }

     

    popup에서는 position을 absolute로 지정

    이러면 top: 100% 경우에는 아이콘 바로 아래에 위치하게 된다.

    아이콘과 팝업에 약간의 공백을 주기위해서 130%로 설정

    아이콘과 같은 위치의 오른쪽에 두기위해 0으로 설정

    #user-popup-container {
      position: absolute;
      width: 200px;
      top: 130%;
      right: 0;
    }

     

    그럼 아이콘 바로 하단에 팝업이 열리게 할 수 있다.


    ForwardRef

    이제 팝업을 제외한 다른 영역을 클릭할 시에 팝업이 닫히게 처리

     

    useEffect를 활용하여 isUserPopup이 true이면 클릭이벤트를 추가하고 

    return cleanUp 함수로 useEffect가 실행되기 전에 즉 팝업이 언마운트 되었을 때

    이벤트를 지우도록 처리

     

    팝업을 제외한 영역에서 클릭을 하면 막아야하기 때문에

    팝업을 닫는 함수에서 클릭한 곳이 팝업 영역인지 파악하기 위해 ref를 사용

    ref로 popup영역을 정해주어 체크

     const popupRef = useRef(null);
     
     useEffect(() => {
            if(isUserPopup) {
                setTimeout(() => {
                    window.addEventListener('click', hadnleClearPopup);
                }, 0);
            }
    
            return () => {
                window.removeEventListener('click',hadnleClearPopup)
            }
        },[isUserPopup])
        
       const hadnleClearPopup = () => {
            if (popupRef.current && !popupRef.current.contains(event.target)) {
                setIsUserPopup(false);
            }
        }

     

    클릭 이벤트를 추가할때 setTimeout을 설정하여 동기 처리로 작동되게 설정

    setTimeout을 사용하지 않으면 비동기 처리가 되며 아이콘을 클릭할때 이벤트가 바로 추가되면서 동시에 팝업을 제외한 영역을 클릭한 것으로 인식하여 팝업이 바로 닫히게 된다.

     

    자식 컴포넌트에 ref를 적용시켜주기 위해서

    ref를 값을 전달하기 위해서는 forwardRef를 사용해야 하므로 forwardRef를 사용하여 ref를 전달하여

    자식 컴포넌트의 팝업 영역을 참조하여 가져올 수 있도록 처리

    import React, { forwardRef } from 'react';
    import './UserPopupComponent.scss';
    
    const UserPopupComponent = forwardRef(({ isOpen, onClose }, ref) => {
        return (
            <>
                {isOpen && (
                    <div id="user-popup-container" ref={ref}>
                        로그인 유저 이메일 정보
                    </div>
                )}
            </>
        );
    });
    
    export default UserPopupComponent;

     

    이렇게 하면 아이콘을 눌렀을 때 팝업이 열리고 이후 팝업을 제외한 다른 영역을 클릭할 시 팝업이 닫히게 된다.

    728x90
    반응형