function Modal({selectedTab}){
let [fade, setFade] = useState('')
useEffect(()=>{
setFade('end')
return ()=>{
setFade("")
}
}, [selectedTab])
return (
<div className={'start' + fade}>
{ [... , ... , ... , ...][selectedTab] }
</div>
)
}
컴포넌트 전환 애니메이션을 주기 위해 다음과 같은 코드를 작성하였지만 의도대로 class가 부착되지 않았다. 리액트 18의 새로운 기능인 Automatic Batching때문이었다.
Automatic Batching은 Reaact가 성능 향상을 위해 여러 개의 state 업데이트를 다 처리한 후에 한 번에 재렌더링을 진행하는 기능이다.
리액트 공식 문서
나는 Fade라는 state를 비운 후에 end라는 값을 넣어주려 했지만 최종적으로 end로만 바뀌게 된 것이다. 리액트 18부터는 ajax, setTimeout 내부에서도 batch기능이 적용된다.
Automatic Batching은 여러개의 state 업데이트마다 발생하는 불필요한 리렌더링을 막아주므로 성능을 높이는 아주 좋은 기능이지만 나는 이 기능이 작동하지 않도록 방지해야 하는 상황이다. setTimeout
으로 시간차를 두어 의도대로 잘 동작시킬 수 있었다.
useEffect(() => {
const timer = () => {
setFade("end");
};
setTimeout(timer, 100);
return ()=>{
clearTimeout(timer);
setFade("")
}
});
다만 이 방법을 사용하면 timer를 clean-up해줘야 함을 유의하자.
React에서는 react-dom에서 특정 상태 업데이트에 대한 재렌더링을 트리거할 수 있는 flushSync() 메서드를 제공하는데 이 메서드를 사용해서도 문제를 해결할 수 있다.
해당 메서드에 대한 자세한 설명과 사용법이 궁금하다면 다음 링크에 접속하기를 권해드립니다.
https://blog.bitsrc.io/automatic-batching-in-react-18-what-you-should-know-d50141dc096e
https://codingapple.com/course-status/
https://nukw0n-dev.tistory.com/33
https://reactjs.org/blog/2022/03/29/react-v18.html