기본 형태
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
function Routing() {
return (
<Router>
<Homenavbar/>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home/>}/>
<Route path="search/:query" element={<Search />} />
<Route path="freeboard" element={<Freeboard />} />
<Route path="freeboardadd" element={<FreeboardADD />} />
<Route path="freeboard/:id" element={<FreeboardDetail />} />
<Route path="freeboardedit/:id" element={<Freeboardedit />} />
<Route path="secreteboard" element={<Secreteboard />} />
<Route path="secreteboard/:id" element={<Secreteboarddetail />} />
<Route path="graduateboard" element={<Graduateboard />} />
<Route path="graduateboard/:id" element={<Graduateboarddetail />} />
<Route path="schedule" element={<Schedule />} />
</Route>
</Routes>
<Routes>
<Route path="/schedule" element={<Schedule/>} />
</Routes>
</Router>
);
}
npm install react-router-dom@latest
Link
export const Eachboardword = styled(Link)`
text-decoration: none;
font-size: 16px;
font-weight: bold;
color: red;
padding: 10px;
`;
<Eachboardword to={`/${board.link}`}>
{board.title}
</Eachboardword>
useParams,useLocation
<Route path= '/mento' element={<Mento/>}/>
<Route path='/mento/:id' element={<Mentoprofile/>}/>
<Boarddiv to ={`mento/${item.id}`}
state={{
selectedKeyword: selectedKeyword
} }
>
import { useParams, useLocation } from "react-router-dom";
const { id } = useParams();
const location = useLocation();
const { selectedKeyword } = location.state || {};
import { Link, useNavigate } from "react-router-dom";
const navigate = useNavigate();
const handleSearchSubmit = (e) => {
e.preventDefault();
if (searchQuery.trim()) {
navigate(`/search/${searchQuery}`);
}
};
//router.js
<Route path="search/:query" element={<Search />} />
특정 페이지들에 고정적인 레이아웃을 부가하고 싶을 때 주로 사용할 수 있는 구조
상위 component를 고정하고 싶은 레이아웃으로 해둔 뒤에 하위 컴포넌트들을 부가.
여기서는 Layout이라는 컴포넌트를 고정하고 싶은 레이아웃으로 지정하였음
<Route path="/" element={<Layout />}>
<Route index element={<Home/>}/>
<Route path="search/:query" element={<Search />} />
<Route path="freeboard" element={<Freeboard />} />
<Route path="freeboardadd" element={<FreeboardADD />} />
<Route path="freeboard/:id" element={<FreeboardDetail />} />
<Route path="freeboardedit/:id" element={<Freeboardedit />} />
<Route path="secreteboard" element={<Secreteboard />} />
<Route path="secreteboard/:id" element={<Secreteboarddetail />} />
<Route path="graduateboard" element={<Graduateboard />} />
<Route path="graduateboard/:id" element={<Graduateboarddetail />} />
<Route path="schedule" element={<Schedule />} />
</Route>
</Routes>
//Layout.js
import React from "react";
import { Outlet } from "react-router-dom";
import styled from "styled-components";
import { Dropdownmenu } from "../components/Home/Homenavbar";
import Rightbar from "./Rightbar";
// Outlet에 router로 하위에 있는 페이지들을 넣는 것 -> routing 체크
const Layout = () => {
return (
<>
<Dropdownmenu />
<LayoutContainer>
<ContentContainer>
<Outlet />
</ContentContainer>
<RightbarContainer>
<Rightbar />
</RightbarContainer>
</LayoutContainer>
</>
);
};
const LayoutContainer = styled.div`
display: flex;
//argin-top: 200px; // Dropdownmenu 높이만큼 패딩 추가
`;
const ContentContainer = styled.div`
flex: 1;
margin-right: 20px; // Rightbar와의 간격 추가
`;
const RightbarContainer = styled.div`
width: 300px; // Rightbar의 고정 너비 설정
`;
export default Layout;
//Dropdownmenu 컴포넌트
const Dropdownmenu=()=>{
return( <DropdownMenu>
<MenuColumn>
<MenuItem to={"/freeboard"}>자유게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>비밀게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>졸업생게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>새내기게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>시사·이슈 <Symbol>•</Symbol></MenuItem>
<MenuItem>장터게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>정보게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>홍보게시판 <Symbol>•</Symbol></MenuItem>
</MenuColumn>
<Separator />
<MenuColumn>
<MenuItem>동아리·학회 <Symbol>•</Symbol></MenuItem>
<MenuItem>취업·진로</MenuItem>
</MenuColumn>
<Separator />
<MenuColumn>
<MenuItem>전산전자공학부 게시판</MenuItem>
<MenuItem>생명과학부 게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>상사학부 게시판 <Symbol>✨</Symbol></MenuItem>
</MenuColumn>
<Separator />
<MenuColumn>
<MenuItem>연애/사랑이야기 <Symbol>•</Symbol></MenuItem>
<MenuItem>콘디 <Symbol>•</Symbol></MenuItem>
<MenuItem>큐피트게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>성 게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>알바생 게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>넷플릭스/왓챠 게시판 <Symbol>•</Symbol></MenuItem>
<MenuItem>끝말잇기</MenuItem>
<MenuItem>썸덕 게시판</MenuItem>
</MenuColumn>
<Separator />
<MenuColumn>
<MenuItem>요리조리킹 <Symbol>•</Symbol></MenuItem>
<MenuItem style={{ color: "#F91F15", fontWeight: "bold" }}>게시판 찾기</MenuItem>
</MenuColumn>
</DropdownMenu>)
}
//Rightbar 컴포넌트
const Rightbar = () => {
return(
<RightSidebar>
<form onSubmit={handleSearchSubmit}>
<SearchBar
placeholder="전체 게시판의 글을 검색하세요!"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</form>
<PopularPosts>
<SectionTitle>실시간 인기 글</SectionTitle>
{boards.slice(0, 2).map((post, index) => (
<Sectioneachboard key={index}>
<Sectionbox height={'75px'} key={post.id} to={`/${post.title}/${post.id}`}>
{post.title}
</Sectionbox>
</Sectioneachboard>
))}
</PopularPosts>
<SidebarSection>
<SectionTitle>HOT 게시물</SectionTitle>
{boards.slice(0, 2).map((post, index) => (
<Sectioneachboard key={index}>
<Sectionbox key={post.id} to={`/${post.title}/${post.id}`}>
{post.title}
</Sectionbox>
</Sectioneachboard>
))}
</SidebarSection>
<SidebarSection>
<SectionTitle>BEST 게시판</SectionTitle>
</SidebarSection>
<SidebarSection>
<SectionTitle>최근 강의평</SectionTitle>
{reviews.map((review, index) => (
<CourseReview key={index}>
<StarRating rating={review.rating} />
<ReviewTitle>{review.title}</ReviewTitle>
<ReviewText>{review.text}</ReviewText>
</CourseReview>
))}
</SidebarSection>
</RightSidebar>
);
};
결과 화면
참고: https://rinn-story.tistory.com/30
참고: https://hsly22xk.tistory.com/405
참고: https://systorage.tistory.com/entry/React-React-Router-v6%EC%97%90%EC%84%9C-query-parameter-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B2%95
참고: https://white120.tistory.com/94
참고: https://velog.io/@kandy1002/React-Router-Dom-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0