React 컴포넌트 전환 애니메이션 (transition)

Inseok Park·2022년 8월 23일
4

React 쇼핑몰 만들기

목록 보기
10/15
post-thumbnail

애니메이션 만들기 3STEP❗

  1. 애니메이션 동작 전, 후 스타일을 담을 className 만들기
  2. CSS에 transition 속성 추가
  3. 원할 때 2번 탈부착 (toggle)

컴포넌트 페이드인 애니메이션을 만들어보기

처음엔 안보이다가 end를 부착할 때 마다 fade-in이 되는 css

.start {
  opacity : 0
}
.end {
  opacity : 1;
  transition : opacity .5s;
}

앞에 만든 탭메뉴 컨텐츠를 fade-in 시켜보기
원할 때 (tab button을 누를 때) end className 부착

function TabContent({tab}){

  let [fade, setFade] = useState('')

  useEffect(()=>{
    setFade('end')
  }, [tab])

  return (
    <div className={'start ' + fade}>
      { [<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][] }
    </div>
  )
}

useEffect 방식의 이론이라면 [tab]디펜던시로 인해 내용이 변하면 end라는 클래스가 적용되어야 한다.
하지만 위 방식은 되지 않는다.

리액트 18버전 이상부터는 automatic batch 라는 기능이 생겼다.
state 변경함수들이 연달아서 여러개 처리되어야한다면
state 변경함수를 다 처리하고 마지막에 한 번만 재렌더링된다.
그래서 'end' 로 state를 변경하는 것과 ' ' 빈값으로 변경하는 효과에 약간 시간차를 두어야한다.
setTimeout 말고 automatic batching을 막아주는 flushSync()를 찾아봐도 좋을 것 같다.

최종 작동코드 (clean-up-function 추가)

function TabContent({tab}){

  // 초기 빈값 (div ClassName='start' 상태)
  let [fade, setFade] = useState('')

  useEffect(()=>{
    // tab의 상태가 변할때 (클릭 후 다른탭 열리면) 0.1초 뒤 'end' className 바인딩
    const fadeTimer = setTImeout(()=>{ setFade('end') }, 100)
    return ()=>{
    // 기존 fadeTimer 제거 후 class 빈 값으로 변경
    clearTimeout(fadeTimer);
  	setFade('')
  }
  }, [tab])

  return (
    <div className={'start ' + fade}>
      { [<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][] }
    </div>
  )
}

추가적으로 위와 같은 방식으로 Detail 컴포넌트 전체에도 fade효과를 넣어보았다!

0개의 댓글