<aside> 🔗
</aside>
등장에서는 패널의 마운트와 등장 애니메이션 사이를 어떻게 관리할지가 핵심이다.
전/후 스타일 간의 차이를 애니메이션으로 보여주는 트랜지션의 특성상, DOM 요소가 화면에 먼저 생성되어 트랜지션 이전 스타일이 적용된 뒤, 트랜지션 이후 스타일이 부여되어야 한다.
따라서 생성 상태와 노출 상태를 따로 두고, 생성 상태가 변할 때마다 노출 상태가 이를 추적하도록 작성한다.
코드
export const TryA1 = () => {
const [isCreated, setIsCreated] = useState(false)
const [isShown, setIsShown] = useState(false)
useEffect(() => setIsShown(isCreated), [isCreated])
return (
<Wrapper>
<Trigger onClick={() => setIsCreated(!isCreated)} />
{isCreated && (
<Panel className={clsx(styles.panel, isShown && styles.show)} />
)}
</Wrapper>
)
}
장점
단점
시도 A1의 단점인 “패널의 생성과 노출 사이의 프레임 차이를 보장하지 않을 수 있음”을 개선하기 위해, 마운트 된 후 "다음 프레임"을 강제한 뒤 스타일 변경을 부여하는 방식이다.
코드
export const TryA2 = () => {
const [isCreated, setIsCreated] = useState(false)
const [isShown, setIsShown] = useState(false)
useEffect(() => {
if (isCreated) {
requestAnimationFrame(() => setIsShown(true))
} else {
setIsShown(false)
}
}, [isCreated])
return (
<Wrapper>
<Trigger onClick={() => setIsCreated(!isCreated)} />
{isCreated && (
<Panel className={clsx(styles.panel, isShown && styles.show)} />
)}
</Wrapper>
)
}
장점
단점
CSS animation을 사용하는 방식이다. CSS animation은 DOM 요소가 생성되는 순간 정의된 동작을 바로 수행할 수 있으므로 별도의 노출 상태가 필요 없다.
코드
.panel {
animation: show 0.3s ease-in-out;
}
@keyframes show {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
export const TryA3 = () => {
const [isCreated, setIsCreated] = useState(false)
return (
<Wrapper>
<Trigger onClick={() => setIsCreated(!isCreated)} />
{isCreated && <Panel className={styles.panel} />}
</Wrapper>
)
}
장점
단점
퇴장에서는 패널의 퇴장 애니메이션과 언마운트 상태를 어떻게 관리할 것인가가 핵심이다.