Next.js + Zustand 기반 프로젝트에서 <Modal />
컴포넌트를 전역으로 사용하고,
setModal(<Component />)
방식으로 multi-step 모달을 구현할 때 Safari에서 아래 문제가 발생:
setModal
을 호출하면 이전 모달은 정상적으로 사라지지만Safari의 렌더링 방식에 다음과 같은 고질적인 버그가 존재함:
opacity
, transform
, backdrop-blur
등의 CSS 트랜지션이 적용 중일 때 React
에서 상태 변경으로 DOM을 교체하는 경우 자주 발생함setModal: (node) => {
set({ isModalOpen: false });
setTimeout(() => {
set({ modalChildren: node, isModalOpen: true });
}, 30);
}
const Modal = () => {
const modalState = useStore(useModalState, (set) => set);
const isOpen = modalState.isModalOpen;
return (
<div
key={`${isOpen}`} // ✅ 상태가 바뀔 때마다 강제 재렌더링
className={`fixed left-1/2 top-0 z-[99] flex h-screen w-[390px] -translate-x-1/2 transform transition-opacity duration-300 max-sm:w-screen ${
isOpen
? "pointer-events-auto animate-fade-in-opacity backdrop-blur-[10px]"
: "pointer-events-none animate-fade-out-opacity"
}`}
>
<div className="relative z-[99] flex h-screen w-full items-center justify-center">
{modalState.modalChildren}
</div>
</div>
);
};
참고로 pointer-events
도 이용해야함. 이 값은 마우스 포인터를 무시하는 역할. pointer-events-none은 투명 처럼 취급하게 됨.