<aside> ❓
a VS Link VS NavLink
https://ramincoding.tistory.com/entry/React-React-Router-NavLink-컴포넌트-VS-Link-컴포넌트
Link 컴포넌트는 a 태그와 유사하지만, 페이지 전환을 방지함 (CSR 처리 가능)
NavLink 컴포넌트는 조건부 로직 처리 편리, 웹 접근성 향상
</aside>
<aside> ❓
NavLink 컴포넌트
https://velog.io/@eunji9128/Active-Links
https://www.heropy.dev/p/9tesDt
<NavLink to="/">Home</NavLink> // alway active
<NavLink to="/" end>Home</NavLink> // only active at "/"
</aside>
import BoardPage from './pages/board/BoardPage'
import Fonts from './styles/fonts'
import { Route, Routes } from 'react-router-dom'
function App() {
return (
<>
<Fonts />
**<Routes>
<Route path="/board" element={<BoardPage />} />
</Routes>**
</>
)
}
export default App
import tw from 'twin.macro'
import { PiClipboardText } from 'react-icons/pi'
import { colors } from '@/styles/colors'
import { NavLink } from 'react-router-dom'
const NavContainer = tw.div`
flex justify-between items-center px-4 pt-3 pb-8 border-t border-t-gray
`
export default function NavBar() {
return (
<NavContainer>
...
{/* Board */}
**<NavLink
to="/board"
style={({ isActive }) => ({
color: isActive ? colors.default : colors.darkGray,
})}
>
<PiClipboardText size="2rem" />
</NavLink>**
...
</NavContainer>
)
}
<Route path="/board/:postId" element={<BoardDetailPage />} />
interface BoardCardProps {
**id: number**
status: string
title: string
authorNickname: string
date: string
chstCount?: number
thumbnailUrl: string
}
export default function BoardCard({
**id,**
status,
title,
authorNickname,
date,
chstCount,
thumbnailUrl,
}: BoardCardProps) {
const badgeData = getBadgeData(status)
return (
**<Link to={`/board/${id}`}>**
<CardContainer>
...
</CardContainer>
</Link>
)
}
import { useNavigate } from 'react-router-dom'
import tw from 'twin.macro'
...
export default function BoardPage() {
**const navigate = useNavigate()
const handleCardClick = (postId: number) => {
navigate(`/board/${postId}`) // 게시글 상세 페이지로 이동
}**
return (
<Container>
<SubHeader title="견적게시판" />
{/* SECTION - 게시글 리스트 영역 */}
<ScrollArea>
**{posts.map((item) => (
<BoardCard
key={item.id}
{...item}
onClick={() => handleCardClick(item.id)}
/>
))}**
</ScrollArea>
<NavBar />
{/* SECTION - 글쓰기 버튼 */}
<BoardWriteBtn />
</Container>
)
}
interface BoardCardProps {
id: number
status: string
title: string
authorNickname: string
date: string
chstCount?: number
thumbnailUrl: string
**onClick: () => void**
}
export default function BoardCard({
status,
title,
authorNickname,
date,
chstCount,
thumbnailUrl,
**onClick,**
}: BoardCardProps) {
const badgeData = getBadgeData(status)
return (
<CardContainer **onClick={onClick}**>
...
</CardContainer>
)
}
import NavBar from '@/components/NavBar'
import { useParams } from 'react-router-dom'
import tw from 'twin.macro'
...
export default function BoardDetailPage() {
**const { postId } = useParams()** *// /board/:postId와 동일한 변수명으로 데이터 꺼내기 가능*
return (
<Container>
...
{/* SECTION - 게시글 상세 영역 */}
<ScrollArea></ScrollArea>
<NavBar />
</Container>
)
}