본 포스팅은 노마드코더의 ReactJs 마스터클래스를 수강한 뒤 작성되었습니다.
본 강의는 react-router-dom 5.4.3 버전을 기준으로 설명되었다.
npm install react-router-dom@5.3.4
∵ 6.4 버전과 5.4.3 버전은 多 차이가 有
본 함수는 브라우저를 좀 더 선언적으로 바꿔준다.
아래는 Router.tsx 파일이다.
import { createBrowserRouter, Route, Routes } from 'react-router-dom";
import App from "./App";
//우리의 Router를 array 형식으로 표현 가능해짐
// path "/"를 부모로 생각하고, 나머지를 children으로 생각하는 것 ❗
const router = createBrowserRouter([
{
//첫번째 route : 전체 route들의 컨테이너 역할
path:"/",
element: <App />,
children: [
{
path:"about",
element: <About />,
},
],
},
]);
export default router;
아래는 App.jsx 파일이다.
우리는 Router.jsx에서 children을 render할때, App이라는 root의 자식 요소를 render한다!라는 것을 알려줘야함.
-> 이 알려주는 작업을 App.jsx에서 < Outlet />를 통해서 해주는 것
import React from "react";
import { Outlet } from "react-router-dom"; //이 부분 추가
function App() {
return (
<div>
<Outlet /> //이 부분 추가
</div>
);
}
export default App;
결론적으로 만약 너가 /about으로 가고 싶다면 아래와 같은 단계를 거치게 되는 것이다.
1. 부모인 path:"/"라는 URL로 매치됨
2. react router는 App을 Render 함
3. App이 children이 有기 때문에, 우리는 App.jsx에서 Outlet이라는 컴포넌트를 사용함
4. react router는 Outlet 컴포넌트를 통해 URL를 보게 되는데, App을 render하고 About도 render하게 됨
∴ Outlet는 우리가 render하고자 하는 route로 바꿔서 render한 것 (자식 route로)
우리의 컴포넌트에 에러가 발생해서 충돌하거나 컴포넌트의 위치를 찾지 못할때 사용됨
-> Root element path (부모 라우팅 요소)에 에러를 추가할 수 있음!!!
∴ 아무런 자식(children)이 발견되지 X았을때 나타남
cost router = createBrowserRouter([
{
path:"/",
element: <Root />,
children: [
{
path: "",
element: <Home />,
},
{
path: "about",
element: <About />,
},
],
//이처럼 제일 아래에 errorElement를 작성하고, 아무 자식도 발견되지 X았을때 (에러 발생) 시 보여줄 요소를 지정해줌
errorElement: <NotFound />, },
]);
여기에는 에러가 발생했을때, 보여줄 화면을 작성하면 됨
-> 유저를 이동시키고 위치를 바꿔줌
예시는 다음과 같다.
const navigate = useNavigate();
const onAboutClick = () => {
navigate("/about");
};
return (
<button onClick={onAboutClick}About</button>
);
다음과 같이 간단하게 회원과 관련된 db를 만들었다고 하자.
export const users = [
{
id: 1,
name: "nico",
},
{
id: 2,
name: "lynn",
},
];
이제 위에 적은 db.ts에 있는 유저들을 나의 홈페이지에 render한다고 해보자
import {users} from "../db";
function Home() {
return (
<div>
<ul>
{users.map(user => (
<li key={user.id}>
<Link to={`/users/${user.id}`}.{user.name}</Link>
</li>
))}
</ul>
</div>
);
}
export default Home;
Home.tsx에서 user의 이름에 대한 link를 클릭했을때, 해당 유저에 대한 정보를 알려주는 페이지
import { useParams } from "react-router-dom";
import { users } from "../../db";
function User() {
const { userId } = useParams();
console.log(userId); //userId에 userId가 有
return (
<h1>
User with it {userId} is named: {users[Number(userId) - 1].name}
</h1>
);
}
export default User;
위에서 만들었던 router.tsx에 아래를 추가한다.
{
path: "users/:userId",
element: <User />,
},
❗ 모든 Outlet 컴포넌트는 Route의 자식들을 render했음
∴ 특정 스크린에서 자식이 有다면, < Outlet />를 쓰면 그 스크린의 자식을 render하게 됨
아래는 예시이다.
function Followers() {
이 Followers.tsx라는 스크린을 User.tsx(위에 有)의 자식으로 추가해보겠다.
{
path: "users/:userId",
element: <User />,
children: [
{
path: "followers",
element: <Followers />,
},
],
},
import { useParams } from "react-router-dom";
import { users } from "../../db";
function User() {
const { userId } = useParams();
console.log(userId); //userId에 userId가 有
return (
<div>
<h1>
User with it {userId} is named: {users[Number(userId) - 1].name}
</h1>
//여기 아래서부터가 추가된 부분
<hr />
/*
Link to="followers"라고 하면 ❗ 상대경로
∴ 현재 URL 뒤에 붙음
Link to="/followers"라고 하면 ❗ 절대경로
∴ 바로 /followers로 됨 (http://localhosts/followers)
*/
<Link to="followers">See followers</Link>
<Outlet />
</div>
);
}
export default User;
context를 Outlet을 통해서 자식 컴포넌트에 필요한 정보들을 보낼 수 있다.
<Outlet
context={{
nameOfMyUser: users[Number(userId)-1].name,
}}
/>
//nameOfMyUser라는 변수에 담아서 context로 보냄
저렇게 context를 통해 보낸 정보인 nameOfMyUser를 이제 자식 컴포넌트에서는 다음과 같이 useOutletContext를 사용해서 받는 것!
import { useOutletContext } from "react-router-dom";
interface IFollowersContext {
nameOfMyUser: string;
}
function Followers() {
const { nameOfMyUser } = useOutletContext(); //정보 받음
return <h1>Here are {nameOfMyUser}'s followers</h1>
}
export default Followers;