(Tab 태그로 한번에 구현 가능하지만 tab 상태에 따라 다른 UI를 구현하는 연습을 위해 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===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]
}
완성도 있는 사이트는 스타일도 한 몫 한다!
애니메이션 만드는 방법
- 동작 전 스타일을 담을 class 만들기
- 동작 후 스타일을 담을 class 만들기
- transition 속성 추가
- 원할 때 탈부착하기
서서히 나타나는 효과를 위해 전일때는 투명도 0, 후일때는 투명도 1로 설정
.start {
opacity : 0
}
.end {
opacity : 1;
}
transition : 해당 속성이 변할 때의 속도 설정
(all
또는속성명
)
.start {
opacity : 0
}
.end {
opacity : 1;
transition : opacity 0.5s;
}
이제 원하는 <div>
요소에 start를 넣어두고 end가 추가될 때마다 fade in 이 된다
탭을 클릭할 때마다 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>
)
}
만약 시간차로 적용시키지 않으면 automatic batch 기능으로 인하여 연달아 위치하는 state 변경함수를 마지막에 하나로 처리한다
그래서 state 변경함수가 연달아 여러개 처리가 되어야 한다면 시간차를 주어야 여러개가 잘 처리된다
실은 떼었다가 붙여야 애니메이션이 보이기 때문이다
하지만 아래처럼 해도 작동이 잘 됨
같은 떼엇다 붙이는 원리라서 그런가보다
useEffect(()=>{
setTimeout(() => setAddClass(true), 500);
return () => setAddClass(false);
},[tab])