제품을 누르면 제품의 상세페이지를,
상단바의 cart 를 누르면 장바구니 페이지를 보여주는 기능을 구현할 것이다.
프레임워크 없이 html 만을 이용해서 구현하는 방법은 새로운 html 파일을 만들어서 상세페이지들을 작성한 후 연결했어야했다.
하지만 리액트를 사용하면 html 파일은 단 하나만 필요하다.
리액트로 상세페이지 구현하는 방법
1. 필요한 페이지들을 컴포넌트로 각각 만든다.
2. 누군가 해당 페이지에 접속하면 그 컴포넌트를 보여준다.
하지만 이러면 html 파일 속 코드 길이가 너~무 길어진다
(진짜) 리액트로 상세페이지 구현하는 방법
: react-router-dom 라이브러리 를 이용한다. 일명 라우팅
1. 먼저 router 라이브러리를 설치하기 위해 터미널에 아래와 같이 입력한다.
npm install react-router-dom@6
2. index.js 파일에 들어가서 <BrowserRouter> 태그를 추가해준다.
3. App.js 파일에서 Route, Routes, Link 를 import 한다.
import { Routes, Route, Link } from 'react-router-dom';
Route 컴포넌트
: 간단하게 페이지 라고 생각하면 된다. 만약 페이지 3개를 만들 것이다? 그러면 아래처럼 구현
function App() {
return (
<div className="App">
<Routes>
<Route />
<Route />
<Route />
</Routes>
...
</div>
)
}
<Router path="/이동url" element={해당 페이지에서 보여줄 코드} />
현재 브라우저의 location 상태에 따라 다른 element를 렌더링한다.
Route.element: 조건이 맞을 때 렌더링할 element, <Element />의 형식으로 전달된다.
Route.path: 현재 path값이 url과 일치하는지 확인해 해당 url에 매칭된 element를 렌더링해준다.
Routes 컴포넌트
: 모든 Route의 상위 경로에 존재해야 하며, location 변경 시 하위에 있는 모든 Route를 조회해 현재 location과 맞는 Route를 찾아준다.
Link 컴포넌트
: 라우터 내에서 직접적으로 페이지 이동 버튼
<Link to="/이동url">아무거나이름</Link>
그래서 한번 상세페이지를 만들어보자!
// App.js
// function App 안에 아래의 코드 작성
<Routes>
{/* 메인페이지 */}
<Route path="/" element={
<>
<div className="main-bg" style={{ backgroundImage : 'url('+ mainImg +')' }}></div>
<div className="container">
<div className="row">
{ shoes.map((a, i)=> {
return <Card shoes={shoes[i]} i={i}></Card>
})}
</div>
</div>
</>
} />
{/* 상세페이지 */}
<Route path="/detail" element={<div>상세페이지 보여주는 척</div>} />
</Routes>
그리고 홈 화면과 상세페이지를 보여줄 링크를 만든다. 따로 만들어도 상관없지만 상단바에 위치하면 더 어울릴 것 같다.
<Navbar bg="dark" data-bs-theme="dark">
<Container>
<Navbar.Brand href="#home">Shopping</Navbar.Brand>
<Nav className="me-auto">
{/* 페이지 이동버튼 */}
<Link to="/">홈</Link>
<Link to="/detail">상세페이지</Link>
</Nav>
</Container>
</Navbar>
이러면 완성!
상세페이지 컴포넌트로 만들기
화면에 나온 신발들의 상세페이지를 만드려고 한다.
Detail 이라는 함수의 컴포넌트를 만들 것이다.
이 함수는 길기 때문에 App.js 파일에 작성하지 않고 따로 Detail.js 파일을 만들 것이다.
function Detail(){
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
</div>
<div className="col-md-6 mt-4">
<h4 className="pt-5">상품명</h4>
<p>상품설명</p>
<p>12,000원</p>
<button className="btn btn-danger">주문하기</button>
</div>
</div>
</div>
)
}
export default Detail;
element 안에 <Detail /> 태그를 입력하면 된다.
import Detail from './Detail.js';
function App() {
...
<Routes>
...
{/* 상세페이지 */}
<Route path="/detail" element={<Detail/>} />
</Routes>
....
}
이렇게 하다보면 파일들이 점점 많아질 것이다.
따라서 비슷한 것끼리 하나의 폴더에 모아주면 된다.
예를 들면, 페이징 기능하는 컴포넌트를 모으기 위해
src 폴더에 routes 라는 폴더를 만들고, 이 폴더 안에 전부 넣어주면 관리하기 편할 것이다.
[ useNavigate ]
페이지 이동을 도와주는 리액트 훅
import { Routes, Route, Link, useNavigate } from 'react-router-dom';
{/* 변수 선언 */}
let navigate = useNavigate()
return (
<div className="App">
<Navbar>
<Container>
<Nav className="me-auto">
{/* navigate 적용 */}
<Nav.Link onClick={()=>{ navigate('/이동할url') }}>화면에 보여지는</Nav.Link>
</Nav>
</Container>
</Navbar>
)
"화면에 보여지는" 이라는 버튼을 누르면 해당 함수가 실행되어 작성한 url 로 이동한다.
만약
navigate(-1)
로 작성하면 뒤로 간다.
(-2, 1, 2 도 다 가능)
[ 404 페이지 ]
<Route path="*" element={<div>없는 페이지</div>} />
[ nested routes & outlet ]
유사한 페이지 여러개를 구현하고 싶을 때 사용한다.
예를 들어 /about 페이지를 만들고,
이 안에 /about/member 페이지, /about/location 페이지 를 만들고 싶다면
import { Routes, Route, Outlet } from 'react-router-dom';
...
<Routes>
<Route path="/about" element={<About/>}>
<Route path="member" element={<div>멤버 페이지</div>} />
<Route path="location" element={<div>위치정보 페이지</div>} />
</Route>
</Routes>
...
function About(){
return (
<div>
<h4>회사정보 페이지</h4>
<Outlet></Outlet>
</div>
)
}
Outlet 태그를 사용하지 않는다면 member, location 의 html 코드가 보이지 않는다.
이렇게 router 를 사용해도 동적인 UI 를 만들 수 있다.
뒤로 가기 버튼도 수월하게 사용 가능하다.
[ url 파라미터 ]
상세페이지가 여러개 생긴다면 router 를 여러개 만들면 될 것같다.
하지만 페이지가 100개라면!?
이럴때 사용하는 것이 url 파라미터 이다.
<Route path="/detail/:id" element={<Detail shoes={shoes} />} />
위 코드는 "/detail/어쩌구 에 접속하면 <Detail shoes={shoes} /> 로 이동해주세요" 라는 의미
그리고 Detail.js 파일에 가서
import { useParams } from 'react-router-dom';
function Detail(props){
let {id} = useParams();
return (
...
<div>
<h4 className="pt-5">{props.shoes[id].title}</h4>
<p>{props.shoes[id].content}</p>
<p>{props.shoes[id].price}원</p>
<button className="btn btn-danger">주문하기</button>
</div>
...
)
}
이러면 detail/1, detail/2. detail/3 url 이동할 때마다 화면에 나타나는 정보가 달라진다.
'⚛️ React' 카테고리의 다른 글
리액트로 쇼핑몰 사이트 만들기 #5 useEffect (0) | 2024.05.10 |
---|---|
리액트로 쇼핑몰 사이트 만들기 #4 styled-component (0) | 2024.05.10 |
리액트로 쇼핑몰 사이트 만들기 #2 데이터 넣기 (import export), 컴포넌트로 바꾸기 (0) | 2024.05.05 |
리액트로 쇼핑몰 사이트 만들기 #1 상단바, 그리드, 이미지 삽입 (0) | 2024.05.05 |
12. 부트스트랩 (0) | 2024.05.02 |