선요약

전체코드

 

- portal을 이용한 Modal의 fade효과 관련 문제점을 해결해주는 전역위치 모달

- 주의점

  • 모달이 생성된 이후부터는 모달내부에서 상태 업데이트를 받기 어려움(전역상태를 이용하면 극복가능)
  • 모달의 전역 context위치에 유의해야함(전역 상태 중 가장 안쪽으로 두어야 안전)

 

 

포탈을 이용한 Modal에 Fade효과 적용시 문제점

흔히 모달 컴포넌트는 portal을 이용해 root위치에 렌더링 되는 방식으로 구현합니다. 그리고 모달의 fade-in, fade-out 효과는 time-out을 이용해 구현하는 방식이 많이 사용되는듯 합니다.

 

그런데 해당 방식으로 프로젝트의 모달을 구현하는데에 한가지 문제가 발생했습니다.

 

 

(위 코드는 mui의 fade Modal 컴포넌트 입니다. Portal을 이용한 Modal 컴포넌트와 유사하게 작동해 예시로 첨부했습니다.)

 

 - 보통의 경우 time-out에 따라 fade효과가 잘 작동되지만 Modal이 포함되어 있는 컴포넌트 자체가 사라지게될 경우 fade-out이 적용되지 않고 modal이 사라지는 현상이 발생합니다.

 - portal로 컴포넌트를 옮겼지만 해당 컴포넌트를 렌더링 하는 뿌리는 변함이 없기 때문에 발생하는 현상으로 보입니다.

 

 

다른 방법: 전역 Context에 컴포넌트를 직접 전달하기

portal을 통해 렌더링되는 컴포넌트를 이동시키는 것이 아니라 컴포넌트 자체를 함수의 인자로 담아 전역 context에서 렌더링 되게끔 구현했습니다.

 

(이에 대한 아이디어는 아래 포스팅을 참고했습니다.)

https://opensource.com/article/21/5/global-modals-react

 

// App.js
const { openModal, closeModal } = useModal();

const handleModalBtnClick = () => {
    openModal(<Modal>일반모달</Modal>);
  };

- openModal 함수로 모달을 컨텍스트에 전달합니다.

 

//ModalContext.js
export const ModalProvider = ({ children }) => {
  const [modalOpened, setModalOpened] = useState(false);
  const [modalComponent, setModalComponent] = useState(null);

  const openModal = (compoenent) => {
    setModalOpened(true);
    setModalComponent(compoenent);
  };

  const closeModal = () => {
    setModalOpened(false);
    setTimeout(() => {
      setModalComponent(null);
    }, 400);
  };

  return (
    <ModalContext.Provider value={{ openModal, closeModal }}>
      <ModalStateContext.Provider value={{ modalOpened }}>
        {children}
        {modalComponent}
      </ModalStateContext.Provider>
    </ModalContext.Provider>
  );
};

-  modalOpened 상태에 따라 Modal 컴포넌트 내부의 opacity가 조정됩니다. 렌더링 여부에는 관여하지 않습니다.

- closeModal 함수를 실행하면 modalComponent 상태값을 null로 지정해 컴포넌트가 사라집니다. 이때 setTimeout api를 이용해 opacity 변동이 끝난 뒤 렌더트리에서 삭제되게끔 합니다.

 

 

전체코드

 

 

장단점

단순히 렌더링하는 컴포넌트가 사라지는 경우에도 fade-out 효과가 남아있게끔 하는 의도로 작성한 코드이지만 그에 따라 파생되는 장단점이 많이 존재합니다.

 

장점

  • 컴포넌트가 사라지는 경우에도 fade-out 효과 적용  
  • 모달을 사용하는 컴포넌트의 직관적이고 정돈된 jsx
    • 특정 컴포넌트 jsx 내부에 직접 모달 컴포넌트가 포함되지 않고 eventHandler의 인자에 담겨있는것이 모달이 표시되는 타이밍을 직관적으로 나타내줌.

단점

  • 모달을 이용하는 컴포넌트와 모달의 상태연동이 유연하지 않음.
    • 모달이 생성된 이후부터는 상태 업데이트를 모달내부에서 받기 어려움(전역상태를 이용하면 극복가능)
    • Modal이 생성되기전 Modal 내부에 함수로 전달된 상태 업데이트함수 등은 정상작동

 

  • 모달의 전역 context위치에 유의해야함(전역 상태 중 가장 안쪽으로 두어야 안전)
    •  전역에 모달이 생성되는만큼 모달 내부에서 전역상태를 이용할 경우(라우팅 등) 모달 context가 이용하려는 context보다 내부에 있어야함.

 

장단점을 따져보고 목적에 맞게끔 portal을 사용할지 전역에 생성할지 선택하면 될듯 합니다.

 

 

 

+ Recent posts