본문 바로가기
STUDY/react.js

[React] 탭 UI 만들기, 컴포넌트 전환 애니메이션 주는 법(transition)

by 히컵 2024. 8. 22.

 

 

 

탭 UI

버튼 3개와 박스 3개를 미리 만들어 놓고 버튼 누를 때마다 그에 맞는 박스를 보여주는UI

 

탭 UI 만들기

1. HTML, CSS로 디자인 미리 완성하기

2. UI의 현재 상태를 저장할 state 하나 만들기

3. state에 따라서 UI가 어떻게 보일지 작성하기

 

참고사항: 자식 컴포넌트에서 props 쉽게 쓰고 싶다면

function TabContent(porps){
  return [ <div>내용0</div>, <div>내용1</div>, <div>내용2</div> ][props.tab]
}

 

function TabContent({tab}){
  return [ <div>내용0</div>, <div>내용1</div>, <div>내용2</div> ][tab]
}

 

자식 컴포넌트에서 props라고 파라미터를 하나만 작명하는 게 아니라 {state1이름, state2이름...} 이렇게 작성하면 props.state1.이름 이렇게 쓰지 않아도 된다.

 

 


 

 

컴포넌트 전환 애니메이션 주는 법(transition)

컴포넌트 등장, 퇴장 애니메이션이 필요하면 라이브러리를 설치해서 사용해도 되지만 간단한 건 CSS를 활용해서 개발이 가능하다. useEffect를 활용하면 된다.

 

애니메이션 만들고 싶으면

1. 애니메이션 동작 전 스타일 담은 className 만들기

2. 애니메이션 동작 후 스타일 담은 className 만들기

3. tranisiton 속성 추가

4. 원할 때 2번 탈부착

 

Detail 컴포넌트 로드시 투명도가 0에서 1로 서서히 증가하는 애니메이션을 만들어 보자.

 

1. 애니메이션 동작 전 스타일 담은 className 만들기,

2. 애니메이션 동작 후 스타일 담은 className 만들기

.start {opacity: 0;}
.end {opacity: 1;}

css 파일에 애니메이션 동작 전에 투명도가 0, 동작 후엔 투명도가 1이 되게 코드를 추가한다.

2. transition 추가

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

이제 원하는 <div> 요소에 start 넣어두고 end를 탈부착할 때마다 fade in이 된다.

 

(Detail.js)

function Detail(props){
    return (
        <Container className='start end'>
            (하단 html 생략)
    )
  }

  export default Detail

end라는 className을 떼었다가 붙여보면 애니메이션이 동작한다.

 

4. 원할 때 end 부착

Detail 컴포넌트 로드시에는 'end'를 부착, Detail 컴포넌트 삭제시에는 'end' 떼기

라고 코드를 작성했다.

(Detail.js)

function Detail(props){
    let [detFade, setDetFade] = useState('');
    useEffect(()=>{
        setDetFade('end')
    }, [])
    return (
        <Container className={"start " + detFade}>
            (하단 html 생략)
    )
  }

  export default Detail

이제 detFade이라는 state가 변할 때마다 fade라는 state는 'end'로 변하고 그러면 className="start end"이렇게 변한다.

버튼을 누르면 end가 부착되니까 애니메이션이 잘 보인다.  안 보임.

이유는 개발자 도구에서 검사해 보면 된다. end라는 클래스명을 부착하는 게 맞는데, 사실은 떼었다가 붙여야 애니메이션이 보인다. end를 떼었다가 다시 붙이면 작동한다.

 

(Detail.js)

function Detail(props){
    let [detFade, setDetFade] = useState('');
    useEffect(()=>{
        setDetFade('end')
        return () => {
            setDetFade('');
        }
    }, [])
    return (
        <Container className={"start " + detFade}>
            (하단 html 생략)
    )
  }

  export default Detail

떼었다가 부착하라고 코드를 작성해 보았다.

clean up function 안에 fade라는 state를 공백으로 바꾸라고 했으니 useEfeect 실행 전엔 'end'가 ' ' 이걸로 바뀐다.

 

실행화면

 

 

(+) setTimeout 쓰는 이유

리액트 18버전 이상부터는 automatic batch라는 기능이 생겼다.

state 변경 함수들이 연달아서 여러개가 처리되어야 한다면 state 변경 함수를 다 처리하고 마지막에 한 번만 재렌더링 된다. 그래서 'end'로 변경하는 거랑 ' '로 변경하는 거를 약간 시간차를 둔 것.

flushSync()를 써도 automatic batching 막아 준다.

 

 

 

 

 

 

* 이 포스팅은 코딩애플 강의를 토대로 작성하였습니다.