<div className="nav">
<span>대메뉴</span>
<ul className="subNav>
<li>소메뉴</li>
</ul>
</div>
- 내가 구현하려고 했던 기능은 위와 같은 코드일 때에 ul-nav를 클릭하면 ul subNav가 보여지는 상황에서 현재 페이지의 url을 파악하여 suvNav>li의 폰트 색상이 인식
- .subNav가 보일 때에는 아이콘이 ↓ 아래를 보게 css가 변화되는 기능을 넣고 싶었음!
참고 이미지
NavLink styled-components 사용
(참고 블로그)[https://yumyumlog.tistory.com/247]
Link는 const StyleLink = styled(Link)
로 작성하면 되는데! NavLink는 스타일드 컴포넌트를 적용할 수 없었다.
NavLink가 아닌 NavLink와 동일한 기능인 url을 인식하여 Link의 style이 변하게 만드는 코드를 따로 작성하여 사용하였다!
import { useState } from "react";
import { Link as RRDLink, useLocation } from "react-router-dom";
import styled from "styled-components";
const Link = ({ children, isActive, ...props }) => {
return <RRDLink {...props}>{children}</RRDLink>;
};
const StyledSubLink = styled(Link)`
text-decoration: none;
font-family: ${({ theme }) => theme.font.point};
font-size: 14px;
color: ${(props) => (props.isActive ? "#64C5B1" : "#101038")};
`;
function NavInnerSub({ item }) {
const { pathname } = useLocation();
return (
<NavInnerButton>
<div className="nav">
<span>대메뉴</span>
<ul className="subNav>
<li to={item.url} isActive={pathname === item.url}>
{item.subName}
</li>
</ul>
</div>
</NavInnerButton>
);
}
export default NavInnerSub;
onClick 이벤트가 발생하면 style이 변하는 기능
onClick 이벤트가 발생하면 아이콘이 ˃ -> ˅
로 변하며 숨겨졌던 navSub가 보이도록 하는 기능 + transition
- ul의 높이를 0에서 auto로 설정할 때에는 transition이 적용되지 않아 라이브러리를 통해 해결하였음. (이전 게시글 참고)
import { useState } from "react";
import styled from "styled-components";
import AnimateHeight from "react-animate-height";
import NavPartList from "./NavPartList";
const NavInnerButton = styled.button`
width: 100%;
height: auto;
padding: 0;
padding-right: 25px;
margin-top: 25px;
margin-left: 30px;
text-decoration: none;
border: none;
background-color: transparent;
text-align: left;
cursor: pointer;
.sub_list {
ul {
width: 180px;
margin-left: 30px;
padding-bottom: 5px;
}
li {
width: 100%;
height: auto;
line-height: 41px;
}
// NavInner Name
& > div {
position: relative;
}
// arrow
& > div:first-child:after,
& > div:first-child::after {
display: block;
content: "";
position: absolute;
right: 0;
top: 10px;
width: 7px;
height: 7px;
border-top: 1px solid ${({ theme }) => theme.colors.pointGray};
border-left: 1px solid ${({ theme }) => theme.colors.pointGray};
transform: rotate(135deg);
transition: all 0.3s ease-in;
}
}
// true가 되어 className에 .sub_list_show가 설정되면 보이는 css
.sub_list_show {
width: 100%;
// arrow
& > div:first-child:after,
& > div:first-child::after {
transform: rotate(225deg);
}
}
`;
function NavInnerSub({ item }) {
// react-animation-height 라이브러리용 state
const [height, setHeight] = useState(0);
// button클릭 시 이벤트 적용 여부를 확인하기 위한 state
const [more, setMore] = useState(false);
const onClickMore = () => {
setMore(!more);
setHeight(height === 0 ? "auto" : 0);
};
return (
<NavInnerButton onClick={onClickMore}>
// more로 현재를 확인한 후, sub를 봐야할 부분은 sub_list_show이라는 className 설정
<div className={more ? "sub_list sub_list_show" : "sub_list"}>
// nav name 컴포넌트
<NavPartList item={item} />
// ul>li 부분
<ul>
{item.subNav.map((item, key) => (
<li key={key}>
<StyledSubLink to={item.url} isActive={pathname === item.url}>
{item.subName}
</StyledSubLink>
</li>
))}
</ul>
</div>
</NavInnerButton>
);
}
export default NavInnerSub;
작성한 코드 전문
import { useState } from "react";
import { Link as RRDLink, useLocation } from "react-router-dom";
import styled from "styled-components";
import AnimateHeight from "react-animate-height";
import NavPartList from "./NavPartList";
const Link = ({ children, isActive, ...props }) => {
return <RRDLink {...props}>{children};
};
const NavInnerButton = styled.button\`
width: 100%;
height: auto;
padding: 0;
padding-right: 25px;
margin-top: 25px;
margin-left: 30px;
text-decoration: none;
border: none;
background-color: transparent;
text-align: left;
cursor: pointer;
.sub\_list {
ul {
width: 180px;
margin-left: 30px;
padding-bottom: 5px;
}
li {
width: 100%;
height: auto;
line-height: 41px;
}
// NavInner Name
& > div {
position: relative;
}
// arrow
& > div:first-child:after,
& > div:first-child::after {
display: block;
content: "";
position: absolute;
right: 0;
top: 10px;
width: 7px;
height: 7px;
border-top: 1px solid ${({ theme }) => theme.colors.pointGray};
border-left: 1px solid ${({ theme }) => theme.colors.pointGray};
transform: rotate(135deg);
transition: all 0.3s ease-in;
}
}
.sub\_list\_show {
width: 100%;
// arrow
& > div:first-child:after,
& > div:first-child::after {
transform: rotate(225deg);
}
}
\`;
const StyledSubLink = styled(Link)`text-decoration: none; font-family: ${({ theme }) => theme.font.point}; font-size: 14px; color: ${(props) => (props.isActive ? "#64C5B1" : "#101038")};`;
function NavInnerSub({ item }) {
const { pathname } = useLocation();
const \[height, setHeight\] = useState(0);
const \[more, setMore\] = useState(false);
const onClickMore = () => {
setMore(!more);
setHeight(height === 0 ? "auto" : 0);
};
return (
<NavInnerButton
aria-expanded={height !== 0}
aria-controls="example-panel"
onClick={onClickMore}
\>
<div className={more ? "sub\_list sub\_list\_show" : "sub\_list"}>
{item.subNav.map((item, key) => (
-
<StyledSubLink to={item.url} isActive={pathname === item.url}>
{item.subName}
))}
);
}
export default NavInnerSub;
'front > react' 카테고리의 다른 글
window사이즈를 확인하여 useSate 값을 변경해 navigation 상태관리하기 - matchMedia (0) | 2022.07.11 |
---|---|
컴포넌트 재사용을 위한 react component 전달 (0) | 2022.07.08 |
styled-components에서 기본 css3로 옮기기 - css3는 네스팅과 변수사용에 제한이 있다 (0) | 2022.07.08 |
height:0; overflow:hidden; -> height:auto; transition animation 적용이 안 될 때 해결 방법 - react-animate-height (0) | 2022.07.04 |
[react] more button & 버튼 클릭하여 표시되는 list 개수 수정 (0) | 2022.06.29 |