갑작스럽게 일들이 많아져서 작성이 좀 늦어졌다. 조금만 시간이 지나도 다시 가물가물해지는게 내 기억력의 한계인가 싶기도 하고, 원래 다 이런건가 스스로에게 위안을 삼아본다.
검색바를 클릭함에 따라 2가지의 형태로 나뉘게 되는 Nav
이전 글에서 이미 확인을 하셨겠지만, 다시 사진을 참조하자면 아래와 같다.
원래 에어비엔비 사이트가 어떤식으로 Nav 가 형성되어있는지 까지는 모르겠다. 에어비엔비 사이트에서는 마치 검색창을 클릭할 시 가운데 검색바가 확대되면서 밑 Nav 처럼 변하는 식으로 되었는데, 시간도 부족하고 아직 방법을 잘 모르겠어서 나의 경우는 opacity 의 변화로 부드럽게 전환되도록 표현하였다.
파일은 2가지로 컴포넌트를 나누어 놨는데, 상위 Nav 컴포넌트에서 조건부 랜더링을 하지 않고, opacity 를 통해서 화면에 보여지는 Nav 를 결정하려고 하였다.
return (
<Section className={toggleNavbar ? null : 'toggle_open zIndex'}>
// 생략
<BottomNavSection>
<Search
startDate={startDate}
endDate={endDate}
location={location}
guest={guest}
setLocation={setLocation}
onChange={onChange}
increseNum={increseNum}
decreseNum={decreseNum}
toggleNav={toggleNav}
toggleNavbar={toggleNavbar}
modalRef={modalRef}
setToggleNavbar={setToggleNavbar}// 클릭을 통해서 toggleNavbar 를 결정시킨다.
/>
</BottomNavSection>
)
export default OnClickSearch;
const Section = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100%;
opacity: 0;
background-color: white;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&.zIndex {
z-index: 102;
}
&.toggle_open { // 이를 부여함으로서 화면상에 Nav를 결정한다.
opacity: 1;
animation-duration: 0.25s;
animation-timing-function: ease-out;
animation-name: ${fadeIn};
animation-fill-mode: both;
}
`;
위 코드는 2가지 Nav 형태 중 한가지 컴포넌트인데, 2가지 모두 같은 구조를 가지기에 나머지 부분은 생략하고, 실제 화면상의 Nav 를 결정짓게 하는 로직을 보여주고자 한다.
Nav 가운데 Search (검색창) 을 클릭할때마다 toggle 이벤트가 발생하여, 매번 toggleNavbar state 가 boolean 으로서 true, false를 번갈아가며 변화하게 된다. 그 상태에 따라 위 코드는 false 일 때 화면에 보여지도록 설정을 해 두었다.
여기서 위에서 설명하였듯, 조건부 랜더링이 아닌 두가지 Nav 를 같이 띄어놓았다고 했는데, 이유는 opacity 에 대한 animation 을 사용하기 위함이다. 즉, 클래스 'toggle_open' 이 활성화 될 때, opacity 가 0 -> 1 로 변화하면서 animation 이 발동을 하게 된다. 즉, opacity 가 0 이기에 보이지는 않을 뿐이지 실제 화면 구성에는 존재한다는 의미이며, 그렇기에 animation 이 작동할 수 있는 것이다.
(animation 은 안보임 -> 보임 사이에 부드러운 전환을 도와주는 것이지, 구성상 없음 -> 생성 사이 전환을 부드럽게 해주는것이 아니다)
또 하나의 특징이 있다면, Nav 가로폭이 메인페이지일 때와 상세페이지일 때 차이가 발생한다는 점인데, 즉, 상세페이지임을 알고 그에 따라 폭을 유동적으로 변경 시켜주어야 한다.
상세페이지임을 Nav가 알게 하는 방법이 어떤게 있을까?
마법처럼 이를 눈치채고 인식하여야 하기에, 고민을 하다가 메인페이지와 상세페이지 간 차이점은 어디서 발생하는지 부터 파악하였다.
메인페이지와 상세페이지의 차이는 간단하게도 url 에서 발생한다. 즉 주소에 /detail 이 포함되어 있느냐 아니냐에 따라서 구별을 해주면 된다는 것을 파악하였다. 이전부터 배워온 방법이 있지않은가. react-router-dom 내 useLocation 을 활용하면 된다.
이를 활용하여 새 변수에 url pathname 을 가져오면 된다. 다시 정리하자면
- useLocation 을 활용하여 pathname 을 가져온다 (현 페이지의)
- pathname 이 '/detail' 이라면 새로운 클래스를 부여하여 폭을 조정해준다.
방법을 알았으니 그대로 적용해보면 된다. 그리고 실제로 적용을 해보려고 하는데 문제가 발생하였다... 왜 인식을 못하지 하면서 고민하다가 아차 싶었던 부분이 있었는데, 바로 pathname 이 완전히 '/detail' 일 때만 클래스를 적용하도록 로직을 구상하였던 것이었다. 당연히 pathname 은 '/detail/:id' 를 가져올 테니 조건과 달라 적용을 안하는게 당연했다.
방법을 변경하여 '/detail' 을 포함하는지 여부를 조건으로 삼았다.
문자열도 배열임을 인지하여 includes 메서드가 사용가능하다는 점을 이용하였다.
const BeforeSearch = ({
startDate,
endDate,
location,
guest,
// 생략
modalIsOpen,
setModalIsOpen,
switchModal,
reroad,
}) => {
let uselocation = useLocation();
let is_detail = uselocation.pathname;
// 생략
return (
<SectionBefore
className={toggleNavbar ? 'toggle_open' : null}
detail={is_detail}
>
<OnClickSearchSection // 포함여부를 따진다. 포함하면 클래스 'detail_width' 적용
className={is_detail.includes('detail') ? 'detail_width' : null}
>
<TopNavSection>
<LogoContainer onClick={reroad}>
// 생략
)
const SectionBefore = styled.div`
position: ${props =>
props.detail.includes('/detail') ? 'relative' : 'fixed'};
top: 0;
left: 0;
width: 100%;
height: 80px;
opacity: 0;
z-index: 102;
background-color: white;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&.toggle_open {
opacity: 1;
animation-duration: 0.25s;
animation-timing-function: ease-out;
animation-name: ${fadeIn};
animation-fill-mode: both;
}
`;
const OnClickSearchSection = styled.div`
width: 100%;
max-width: 1760px;
margin: 0 auto;
padding: 0 80px;
&.detail_width {
padding: 0;
max-width: 1170px;
}
`;
위 코드에서 알 수 있듯이 '/detail' 포함 여부에 따라 position 과 width 에 변화를 주고 있다. 이로서 상세페이지에선 그에 맞는 Nav 형태를 표현할 수 있게 되었다.
기억을 더듬으면서 쓰는것도 이유겠지만, Nav 를 만들당시 고려했던 점이 참 많았던....
쓰다보니 어느덧 저녁시간이라 다음글을 마지막으로 Nav 부분을 마무리 하려고한다. 지난 글들을 되돌아보니 굵직굵직한 메인페이지처럼 눈에 확 띄지는 않지만 생각했던것 보다 다양한 변수상황들을 고려했어야 했기에, 작성할 부분들이 많았던 것 같다.
시간지나 다시 또 돌려봐야할듯 싶다
'Programing > React' 카테고리의 다른 글
SSR(Server Side Rendering) & CSR (2) | 2022.09.25 |
---|---|
2차 프로젝트 - 에어비엔비 Nav(7) (0) | 2022.09.17 |
2차 프로젝트 - 에어비엔비 ProfileContainer(5) (0) | 2022.09.04 |
2차 프로젝트 - 에어비엔비 우측 상단 프로필 버튼(4) (0) | 2022.09.03 |
2차 프로젝트 - 에어비엔비 상단 검색창 - Location, Calender, User(3) (2) | 2022.08.31 |