탭을 클릭할 때마다 부드럽게 전환되도록 애니메이션 적용해봅시다.
간단히 내용을 정리하자면 애니메이션 설정을 먼저 한 후, 그 애니메이션을 지정할 곳에 className을 붙이면 적용할 수 있습니다.
CSS
.start {
opacity: 0;
}
.end {
opacity: 1;
transition: opacity .5s ;
}
시작 지점에 투명도를 0, 끝나는 지점에 투명도를 1로 주고, transition 값을 부여하였습니다.
JS
// 생략
<Nav variant="tabs" defaultActiveKey="link0">
<Nav.Item>
<Nav.Link eventKey="link0" onClick={()=>{setTab(0)}}>버튼0</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="link1" onClick={()=>{setTab(1)}}>버튼1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="link2" onClick={() =>{setTab(2)}}>버튼2</Nav.Link>
</Nav.Item>
</Nav>
<TabContent tab={tab} setTab={setTab}/>
</div>
)
}
function TabContent({tab}){
return <div className="start end">
{[<div>내용 0</div>,<div>내용 1</div>,<div>내용 2</div>][tab]}
</div>
}
탭 컴포넌트에 전환애니메니션 값이 들어있는 start와 end클래스 명을 넣어주었습니다.
잠깐! 근데 위 상태로 두면 전환이 이루어지지 않고 end 클래스를 떼었다가 붙일 때 애니메이션이 일어납니다.
즉, 탭을 클릭할 때 마다 end가 나타나게끔 해주어야 합니다.
탭을 클릭할 때 마다 end 클래스 붙여주기
function TabContent({tab}){
let [fade, setFade] = useState('');
useEffect(() => {
setTimeout(()=> {setFade('end')}, 100)
return ()=>{
setFade('')
}
},[tab])
return <div className={`start ` + fade}>
{[<div>내용 0</div>,<div>내용 1</div>,<div>내용 2</div>][tab]}
</div>
}
상태 변화가 일어날 때 마다 실행시켜주는 useEffect()를 사용하였습니다. setFade가 빈칸이었다가 0.1초의 시간차를 두고 setFade('end')가 됩니다.
여러개의 state 변경 함수를 한번에 묶어 리랜더링하는 리액트의 automatic batch 기능 때문에 의도적으로 시간차를 주고 end가 붙여지게끔 한것입니다.