[React] 16. 탭 UI 만들기 (+transition 으로 애니메이션 주기)

지렁·2023년 11월 8일
0
post-custom-banner

상세페이지에 tab 만들기

  • 상세정보, 후기, 질문 tab을 만들어보겠다


🖤 Tab UI 구현

(Tab 태그로 한번에 구현 가능하지만 tab 상태에 따라 다른 UI를 구현하는 연습을 위해 Nav를 사용함)

✨ tab Nav 구현

우선 부트스트랩에서 Nav 태그를 가져오고 tab state를 만들었다

let [tab,setTab]=useState(0)

각 탭의 상태를 0,1,2로 저장할것이다

이제 해당 tab을 클릭할 때마다 onClick 속성을 이용하여 tab의 값을 변경해준다

<Nav variant="tabs" className="my-5" fill defaultActiveKey="link0">
  <Nav.Item>
    <Nav.Link onClick={()=>setTab(0)} eventKey="link0">상세정보</Nav.Link>
  </Nav.Item>
  <Nav.Item>
    <Nav.Link onClick={()=>setTab(1)} eventKey="link1">후기</Nav.Link>
  </Nav.Item>
  <Nav.Item>
    <Nav.Link onClick={()=>setTab(2)} eventKey="link2">질문</Nav.Link>
  </Nav.Item>
</Nav>

✨ Tab 별 컨텐츠 구현

그릐고 탭을 클릭할 때 보여줄 컨텐츠를 만들어보았다

{tab===0 && <div>상세정보입니다</div>}
{tab===1 &&<div>구매 후기입니다</div>}
{tab===2 &&<div>질문 게시판입니다</div> }

음... 조건문이 많으니 뭔가 복잡해졌다

깔끔한 코드를 위해 컴포넌트로 만드는게 좋겠다

<TabContent tab={tab}/>

tab을 전달받고 tab을 0,1,2로 저장했던 것을 이용하여 배열인덱싱을 하였다

function TabContent({tab}){
    return [<div>상세정보입니다</div>,<div>구매 후기입니다</div>,<div>질문 게시판입니다</div>][tab]
  }


🖤 애니메이션 효과 주기

완성도 있는 사이트는 스타일도 한 몫 한다!

  • 탭의 내용이 서서히 등장하는 fade in 애니메이션 추가

애니메이션 만드는 방법

  1. 동작 전 스타일을 담을 class 만들기
  2. 동작 후 스타일을 담을 class 만들기
  3. transition 속성 추가
  4. 원할 때 탈부착하기

1. 동작 전/후 class 만들기

서서히 나타나는 효과를 위해 전일때는 투명도 0, 후일때는 투명도 1로 설정

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

2. transition 추가

transition : 해당 속성이 변할 때의 속도 설정
( all 또는 속성명)

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

이제 원하는 <div> 요소에 start를 넣어두고 end가 추가될 때마다 fade in 이 된다

3. 원할 때 탈부착

탭을 클릭할 때마다 end를 해당 div에 부착하기

tab state 값이 변경될 때마다 end를 추가하면 될 것 같다

 function TabContent({tab}){

    //tab 상태가 변할 때마다 코드를 실행시키기 위해 useEffect 사용
    useEffect(()=>{
  document.querySelector('.start').classList.add('end')
    },[tab])

    return (
      <div className='start'>
        {[<div>상세정보입니다</div>,<div>구매 후기입니다</div>,<div>질문 게시판입니다</div>][tab]}
      </div>
    )
  }

tab 값이 변경될 때마다 코드를 실행시키기 위해 useEffect를 사용하였고,
우선 자바스크립트 문법으로 해당 div에 end 클래스를 추가해보았다

하지만 이건 리액트에서 권장하는 방식이 아니다

리액트에서는 직접 DOM을 조작하는 것보다 상태와 속성(props)을 기반으로 렌더링을 관리하는 방식을 선호

그래서 컴포넌트 상태를 이용해 클래스를 동적으로 할당해보겠다

addClass state를 만들어서 tab 값이 변경되면 true로, 탭이 mount 될 때 false로 변경할 것이다

function TabContent({tab}){

    let [addClass,setAddClass]= useState(false)

    //tab 상태가 변할 때마다 코드를 실행시키기 위해 useEffect 사용
    useEffect(()=>{
      setTimeout(() => setAddClass(true), 500);
      return () => setAddClass(false);
    },[tab])

    return (
      <div className={`start ${addClass ? 'end': ''}`}>
        {[<div>상세정보입니다</div>,<div>구매 후기입니다</div>,<div>질문 게시판입니다</div>][tab]}
      </div>
    )
  }

🤔 setTimeout 사용이유는?

만약 시간차로 적용시키지 않으면 automatic batch 기능으로 인하여 연달아 위치하는 state 변경함수를 마지막에 하나로 처리한다

그래서 state 변경함수가 연달아 여러개 처리가 되어야 한다면 시간차를 주어야 여러개가 잘 처리된다

🤔 clean up function 사용 이유는?

실은 떼었다가 붙여야 애니메이션이 보이기 때문이다
하지만 아래처럼 해도 작동이 잘 됨
같은 떼엇다 붙이는 원리라서 그런가보다

 useEffect(()=>{
      setTimeout(() => setAddClass(true), 500);
      return () => setAddClass(false);
    },[tab])
profile
공부 기록 공간 🎈💻
post-custom-banner

0개의 댓글