벨로퍼트 리액트 - 5. 리액트 라우터
** 예제는 라우터 V5지만 내가 설치한건 V6이라 코드가 약간 다르다
5-3. 서브라우트
서브라우트 : 라우트 내부의 라우트를 만드는 것. 컴포넌트를 만들어서 그 안에 Route 컴포넌트를 렌더링 하면 된다.
예제) Profiles.js
import React from "react";
import { Link, Routes, Route } from 'react-router-dom';
import Profile from './Profile';
const Profiles = () => {
return (
<div>
<h3>유저 목록 :</h3>
<ul>
<li>
<Link to="/profiles/harry">harry</Link>
</li>
<li>
<Link to="/profiles/tester11">tester11</Link>
</li>
</ul>
<Routes>
{/* element에 직접 태그 입력 = JSX 렌더링 가능. 상위 영역에서 props등 기타값 전달 가능 */}
<Route path='/' element={<div>유저를 선택해주세요</div>} />
<Route path=':username' element={<Profile/>} />
</Routes>
</div>
);
}
export default Profiles;
⇒ App.js 변경
import React from 'react';
import { Route, Routes, Link } from 'react-router-dom';
import About from './About';
import Home from './Home';
import Profiles from './Profiles';
const App = () => {
return (
<div>
<ul>
<li>
<Link to="/">홈</Link>
</li>
<li>
<Link to="/about">소개</Link>
</li>
<li>
<Link to="/profiles">프로필 목록</Link>
</li>
</ul>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/*" element={<Profiles />} />
</Routes>
</div>
);
};
export default App;
결과 화면
** 특정 라우트 내에 탭 등의 요소를 구현할 경우, state로 관리하는 것보다 서브라우트로 하는것이 권장된다. ⇒ setState를 할 필요도 없고 링크를 통해 다른 페이지에서 쉽게 진입도 가능하기때문.
5-4. 리액트 라우터 부가기능
history 객체 ⇒ useNavigate() 사용
useNavigate는 양식이 제출되거나 특정 이벤트가 발생할때 url을 조작할 수 있는 인터페이스를 제공한다.
import { useNavigate } from 'react-router-dom';
function Func() {
const navigate = useNavigate();
const onClickImg = () => {
navigate("../success", {replace: (true or false) / state : (any)});
};
return (
<img src={...} alt={...} onClick={onClickImg} />
);
}
export default Func;
useNavigate의 첫번째 인자는 주소를 받으며 두번째 인자로는 replace와 state 인수를 사용한다.
- replace (true or false) : true일 경우 navigate에 적힌 주소로 넘어간 후 뒤로가기를 하더라도 이전의 페이지로 돌아가지 않고 자신의 메인 페이지(”/”)로 돌아가게 된다. false(기본값)일 경우 뒤로가기가 가능하다.
- state (any) : navigate(to, { state })와 같은 형태로 사용 가능하다. to에는 <Link>에서 사용한 to=' '와 동일한 내용을 넣어주면 된다.
예제) HistorySample.js
import React from "react";
import { useNavigate } from "react-router-dom";
function HistorySample() {
const navigate = useNavigate();
const goBack = () => {
const confirm = window.confirm('이전 페이지로 이동하시겠습니까?');
if (confirm) {
navigate(-1); // 이동할 페이지의 주소나 index 값을 넣는다. 음수는 이전, 양수는 다음페이지
}
};
const goHome = () => {
navigate('/');
};
return (
<div>
<button onClick={goBack}>뒤로가기</button>
<button onClick={goHome}>홈으로</button>
</div>
)
}
export default HistorySample;
withRouter Hoc ⇒ v6에서는 사라진 기능
컴포넌트가 아닌 곳에서 match / loaction / history 를 사용해야 할때
❗❗v6 변경사항❗❗
- match 대신 useParams() 사용
- location 대신 useLocation() 사용
- history, useHistory 대신 useNavigate() 사용
예제) WithRouterSample.js
import React from "react";
import { useParams, useLocation, useNavigate } from 'react-router-dom';
const WithRouterSample = () => {
const params = useParams(); // url에 대한 정보
const location = useLocation(); // 현재 페이지에 대한 정보
const navigate = useNavigate();
return (
<div>
<h4>params</h4>
<textarea value={JSON.stringify(params)} readOnly />
<h4>location</h4>
<textarea value={JSON.stringify(location, null, 2)} readOnly />
<h4>navigate</h4>
<button onClick={() => navigate(-1)}>홈으로</button>
</div>
)
}
export default WithRouterSample;
결과화면
Not Found 페이지 구현(Switch → Routes로 변경됨)
App.js 수정
const {pathname} = useLocation();
return (
<div>
...
<Routes>
...
{/* path를 따로 정의하지 않으면 모든 상황에 렌더링 됨 */}
<Route path='/*' element={<h1>이 페이지는 존재하지 않는 페이지 입니다. - { pathname }</h1>}/>
</Routes>
</div>
);
NavLink - 현재 페이지가 액티브인지 아닌지 알수있음
브레드 크럼이나 탭과 같은 탐색메뉴 작성시 유용.
Profiles.js 수정
import React from "react";
import { NavLink, Routes, Route } from 'react-router-dom';
import Profile from './Profile';
import WithRouterSample from "./WithRouterSample";
import "./Profiles.css";
const style = {
background : 'black',
color: '#fff',
}
const Profiles = () => {
return (
<div>
<h3>유저 목록 :</h3>
<ul>
<li>
<NavLink style={({isActive}) => isActive ? style : undefined} to="/profiles/harry">harry</NavLink>
</li>
<li>
<NavLink className={({isActive})=>isActive ? "classStyle" : undefined} to="/profiles/tester11">tester11</NavLink>
</li>
</ul>
<Routes>
{/* element에 직접 태그 입력 = JSX 렌더링 가능. 상위 영역에서 props등 기타값 전달 가능 */}
<Route path='/' element={<div>유저를 선택해주세요</div>} />
<Route path=':username' element={<Profile/>} />
</Routes>
<WithRouterSample /> {/* 라우트팅이 아니니 Routes 밖에! */}
</div>
);
}
export default Profiles;
Profiles.css
.classStyle {
background: green;
font-weight: bold;
color: #fff;
}
결과화면