오늘은 프로젝트를 진행하던중 피드백받았고 어려웠던점을 적어보겠다.
lnb를 만들고 구성하는데 분기처리의 대한 이슈와 효율성의 이슈였다.
현재 서비스 영역만 해당되는 네비게이션이다.
서브메뉴,중분류 메뉴, 각 서브 분류별 사용되는 메뉴 바이다.
기존의 lnb는
<script>
import LnbCommunity from "@globalComponents/lnbItem/LnbCommunity"
import LnbEducation from "@globalComponents/lnbItem/LnbEducation"
import LnbInfo from "@globalComponents/lnbItem/LnbInfo"
import LnbService from "@globalComponents/lnbItem/LnbService"
import LnbSocialService from "@globalComponents/lnbItem/LnbSocialService"
import { useRouter } from "next/router"
import React, { useState } from "react"
import * as S from "./Lnb.style"
const Lnb = () => {
const [subTheme, setSubTheme] = useState("")
const router = useRouter()
const urlPath: string = router.asPath
const urlPathArray = urlPath.split("/")
const urlMainKeyword = urlPathArray[1]
const lnbRender = () => {
switch (urlMainKeyword) {
case "info": {
const theme = "회사소개"
return <LnbInfo theme={theme} setSubTheme={setSubTheme} subTheme={subTheme} />
}
case "service": {
const theme = "돌봄서비스신청"
return <LnbService theme={theme} setSubTheme={setSubTheme} subTheme={subTheme} />
}
case "education": {
const theme = "교육안내"
return <LnbEducation theme={theme} setSubTheme={setSubTheme} subTheme={subTheme} />
}
case "social_service": {
const theme = "사회서비스"
return <LnbSocialService theme={theme} setSubTheme={setSubTheme} subTheme={subTheme} />
}
case "community": {
const theme = "커뮤니티"
return <LnbCommunity theme={theme} setSubTheme={setSubTheme} subTheme={subTheme} />
}
}
}
return (
<S.Wrapper>
<div>{lnbRender()}</div>
</S.Wrapper>
)
}
</script>
export default Lnb
로 lnb를 구성했고 각각의 분기처리를 맡았고 5개의 컴포넌트의 내용은 아래와 비슷한 내용의 컴포넌트가 반복됐다.
<script>
import LnbCurrentLocation from "@globalComponents/lnbCurrentLocation/LnbCurrentLocation"
import Link from "next/link"
import React, { FC, useEffect } from "react"
interface Props {
theme: string
setSubTheme: React.Dispatch<React.SetStateAction<string>>
subTheme: string
}
const LnbCommunity: FC<Props> = ({ theme, setSubTheme, subTheme }) => {
useEffect(() => {
setSubTheme("공지사항")
}, [])
return (
<div>
<LnbCurrentLocation theme={theme} subTheme={subTheme} />
<div className="lnb_container">
<h3 className="lnb_main_theme">커뮤니티</h3>
<ul className="lnb_list">
<Link href="http://localhost:3000/community/notice">
<a>
<li
className={subTheme === "공지사항" ? "checked_subtheme" : "defalut"}
onClick={() => setSubTheme("공지사항")}
>
공지사항
</li>
</a>
</Link>
<Link href="http://localhost:3000/community/parenting_information">
<a>
<li
className={subTheme === "육아정보" ? "checked_subtheme" : "defalut"}
onClick={() => setSubTheme("육아정보")}
>
육아정보
</li>
</a>
</Link>
<Link href="http://localhost:3000/community/gallery">
<a>
<li
className={subTheme === "포토갤러리" ? "checked_subtheme" : "defalut"}
onClick={() => setSubTheme("포토갤러리")}
>
포토갤러리
</li>
</a>
</Link>
<Link href="http://localhost:3000/community/qna">
<a>
<li
className={subTheme === "질문과답변" ? "checked_subtheme" : "defalut"}
onClick={() => setSubTheme("질문과답변")}
>
질문과답변
</li>
</a>
</Link>
</ul>
</div>
</div>
)
}
</script>
export default LnbCommunity
useEffect를 사용하여 첫페이지에 접속하면 첫페이지의 1장에 해당하는 setSubTheme를 정해주었다.
이런 상황에서 어떻게 줄여나가고 반복사항을 어떻게 줄일까의 고민에 봉착했다.
쉽게 잘 변경되지않는 nav바의 depth에 대한 영역이기에 dummy data를 만들고 분기처리를 하면 효율적으로 처리할 수 있을 것 같다고 피드백을 들었다.
그렇기때문에 개선의 대한 구조와 중복제거의 중점을 두고
<script>
export const data: MenuList = [
{
title: "회사소개",
depth1: "info",
href: "/info",
list: [
{ title: "대표인사말", href: "/info" },
{ title: "회사연혁", href: "/info/history" },
{ title: "사회적기업", href: "/info/se" },
{ title: "오시는길", href: "/info/map" }
]
},
{
title: "돌봄서비스신청",
depth1: "service",
href: "/service",
list: [
{ title: "돌봄서비스안내", href: "/service/info" },
{ title: "돌봄서비스신청", href: "/service/service" },
{ title: "이용요금안내", href: "/service/price" },
{ title: "자주하는질문", href: "/service/questions" },
{ title: "돌봄이용후기", href: "/service/review_babysitter" }
]
},
{
title: "교육안내",
depth1: "education",
href: "/education/babysitter",
list: [
{ title: "아동양육지도사", href: "/education/babysitter" },
{ title: "놀이학습지도사", href: "/education/play" },
{ title: "보육사 지원안내", href: "/education/job" },
{ title: "보수교육", href: "/education/additional_education" },
{ title: "교육안내", href: "/education/educational_guidance" }
]
},
{
title: "사회서비스",
depth1: "social_service",
href: "/social_service/current",
list: [
{ title: "사회서비스 현황", href: "/social_service/current" },
{ title: "보육서비스와 사회적기업", href: "/education/play" }
]
},
{
title: "커뮤니티",
depth1: "community",
href: "/community/notice",
list: [
{ title: "공지사항", href: "/community/notice" },
{ title: "육아정보", href: "/community/parenting_information" },
{ title: "포토갤러리", href: "/community/gallery" },
{ title: "질문과답변", href: "/community/qna" }
]
}
]
</script>
위와같이 dummy를 만들었다.
그리고
<script>
import Link from "next/link"
import { useRouter } from "next/router"
import React from "react"
import { data } from "../header/_Gnb_desktop"
import * as S from "./MainLnb.style"
function MainLnb() {
const router = useRouter()
const aspath = router.asPath
const currentMenu = router.asPath.split("/")[1]
const menuItemObj = data.find((currentLocationData) => currentLocationData.depth1 === currentMenu)
const menuDepth_1_title = menuItemObj?.title
const menuList = menuItemObj?.list
if (!menuList) return //타입가드 메뉴리스트가 없을 수 있기때문에
const menutitle = menuList.filter((menuItem) => (menuItem.href === aspath ? menuItem.title : null))[0].title
//메뉴리스트 순회하면서 현재 패스와 아이템의 href가 일치하는 case를 찾고 일치하면 일치한 title을 뿌림 배열반환이니까 [].title로접근
return (
<S.Wrapper>
<div className="current_location_info_box">
<div className="character_img_container">
<img className="character_img" src="https://dasar.co.kr/images/img_sub_ico.png" alt="character_img" />
</div>
<h3 className="menu_category_title">{menuDepth_1_title}</h3>
<span className="classification_mark"> > </span>
<span className="menu_category_depth1">{menutitle}</span>
</div>
<div className="baby_img_container">
<img className="baby_img" src="https://dasar.co.kr/images/img_sub.png" alt="baby_img" />
</div>
<ul className="menu_list">
<h3 className="menu_category">{menuDepth_1_title}</h3>
{menuList?.map((menuItem, i) => {
const itemStateClass = aspath === menuItem.href ? "checked_lnb_list_item" : "lnb_list_item"
return (
<div key={i}>
<Link href={`${menuItem.href}`}>
<a>
<li className={itemStateClass}>{menuItem.title}</li>
</a>
</Link>
</div>
)
})}
</ul>
</S.Wrapper>
)
}
export default MainLnb
</script>
기존의 5개의 컴포넌트 ,글로벌 css ,불필요한 props 드릴링 이슈로 위처럼 개선했다 .
asPath를 split으로 자르고 인덱스 값을 추출하여 원하는 현재 경로를 추출했다.
data라는 dummy데이터를 임포트해서 data.find를 통해 배열을 순회하면서 위에서 추출한 값이랑 비교하며 첫번째로 나온 요소를 리턴한다.
그 리턴값을 통하여 list배열의 접근하고 그 값으로 맵을 돌려서 안에 요소들을 화면에 그려주고 현재 path와 href가 같다면 클레스를 조건부로 넣어 현재 경로에대한 css요소를 추가해주었다.
router처리와 asPath와 더미의 href값을 적절하게 설정하여 불필요하게 반복되는 현상을 제어 할 수 있었다.