[React] Router
1. React Routing 이해하기
- Single Page Application
- 기존에는 서버로부터 해당 url에 대한 데이터를 받아옴
- 이제는 서버로부터 하나의 전체 App 받아온 후 클라이언트(Browser)에서 url에 따라서 어떤 것을 보여줄지 결정
- SPA 라우팅 과정
- 브라우저에서 최초에 ‘/’ 경로로 요청
- React Web App을 내려줌
- 내려받은 React App에서 ‘/’ 경로에 맞는 Component를 보여줌
- React App에서 다른 페이지로 이동하는 동작을 수행하면,
- 새로운 경로에 맞는 Component를 보여줌
- cra에 기본 내장된 패키지가 아님
- react-router-dom은 Facebook의 공식 패키지는 아님
- 가장 대표적인 라우팅 패키지
# terminal
$ npx create-react-app react-router-example
$ cd react-router-example
$ npm i react-router-dom
$ code .
$ npm start
- 특정 경로에서 보여줄 component 준비
- ’/’ => Home Component
- ‘/profile’ => Profile Component
- ‘/about’ => About Component
// src/pages/Home.jsx
export default function Home() {
return <div>Home 페이지</div>;
}
// src/pages/Profile.jsx
export default function Profile() {
return <div>Profile 페이지</div>;
}
// src/pages/About.jsx
export default function About() {
return <div>About 페이지</div>;
}
// src/App.js
// Route Component에 path와 component를 설정하여 나열
import { BrowserRouter, Route } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
function App() {
return (
// BrowserRouter로 Route를 감싸줌
// Browser에서 요청한 경로에 Route의 path가 들어있으면 해당 Component를 보여줌
<BrowserRouter>
<Route path="/" exact component={Home} />
<Route path="/profile" component={Profile} />
<Route path="/about" component={About} />
</BrowserRouter>
);
}
export default App;
2. Dynamic Routing
// src/App.js
import { BrowserRouter, Route } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
function App() {
return (
<BrowserRouter>
<Route path="/" exact component={Home} />
<Route path="/profile" exact component={Profile} />
<Route path="/profile/:id" component={Profile} />
<Route path="/about" component={About} />
</BrowserRouter>
);
}
export default App;
// src/pages/Profile.jsx
export default function Profile(props) {
const id = props.match.params.id;
console.log(id, typeof id);
return (
<div>
<h2>Profile 페이지</h2>
{id && <p>id는 {id}입니다.</p>}
</div>
);
}
// src/pages/About.jsx
export default function About(props) {
const searchParams = props.location.search;
console.log(searchParams);
const obj = new URLSearchParams(searchParams);
console.log(obj.get("name"));
return <div>About 페이지</div>;
}
// ---------------------------------------------------
import queryString from "query-string";
export default function About(props) {
const searchParams = props.location.search;
console.log(searchParams);
const query = queryString.parse(searchParams);
console.log(query);
return (
<div>
<h2>About 페이지</h2>
{query.name && <p>name은 {query.name} 입니다.</p>}
</div>
);
}
3. Switch와 NotFound
- 여러 Route 중 순서대로 먼저 맞는 하나만 보여줌
- exact를 뺄 수 있는 로직을 만들 수 있음
- 가장 마지막에 어디 path에도 맞지 않으면 보여지는 Component를 설정해서, “Not Found” 페이지를 만들 수 있음
// src/App.js
import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/profile/:id" component={Profile} />
<Route path="/profile" component={Profile} />
<Route path="/about" component={About} />
<Route path="/" exact component={Home} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
}
export default App;
// src/pages/NotFound.jsx
export default function NotFound() {
return <div>페이지를 찾을 수 없습니다.</div>;
}
4. JSX 링크로 Routing 이동하기
// src/App.js
import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
import Links from "./components/Links";
function App() {
return (
<BrowserRouter>
<Links />
<Switch>
<Route path="/profile/:id" component={Profile} />
<Route path="/profile" component={Profile} />
<Route path="/about" component={About} />
<Route path="/" exact component={Home} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
}
export default App;
// src/components/Links.jsx
import { Link } from "react-router-dom";
export default function Links() {
return (
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/profile">Profile</Link>
</li>
<li>
<Link to="/profile/LWW">Profile/LWW</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/about?name=LWW">About?name=LWW</Link>
</li>
</ul>
);
}
- import { NavLink } from ‘react-router-dom’;
- activeClassName, activeStyle처럼 active 상태에 대한 스타일 지정 가능
- Route의 path처럼 동작하기 때문에 exact가 있음
// src/App.js
import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
import Links from "./components/Links";
import NavLinks from "./components/NavLinks";
function App() {
return (
<BrowserRouter>
<Links />
<NavLinks />
<Switch>
<Route path="/profile/:id" component={Profile} />
<Route path="/profile" component={Profile} />
<Route path="/about" component={About} />
<Route path="/" exact component={Home} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
}
export default App;
// src/components/NavLinks.jsx
import { NavLink } from "react-router-dom";
const activeStyle = { color: "royalblue" };
export default function NavLinks() {
return (
<ul>
<li>
<NavLink to="/" exact activeStyle={activeStyle}>
Home
</NavLink>
</li>
<li>
<NavLink to="/profile" exact activeStyle={activeStyle}>
Profile
</NavLink>
</li>
<li>
<NavLink to="/profile/LWW" activeStyle={activeStyle}>
Profile/LWW
</NavLink>
</li>
<li>
<NavLink
to="/about"
activeStyle={activeStyle}
isActive={(match, location) => {
console.log(match, location);
return match !== null && location.search === "";
}}
>
About
</NavLink>
</li>
<li>
<NavLink
to="/about?name=LWW"
activeStyle={activeStyle}
isActive={(match, location) => {
return match !== null && location.search === "?name=LWW";
}}
>
About?name=LWW
</NavLink>
</li>
</ul>
);
}
5. JS로 Routing 이동하기
// src/App.js
import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
import Login from "./pages/Login";
import Links from "./components/Links";
import NavLinks from "./components/NavLinks";
function App() {
return (
<BrowserRouter>
<Links />
<NavLinks />
<Switch>
<Route path="/login" component={Login} />
<Route path="/profile/:id" component={Profile} />
<Route path="/profile" component={Profile} />
<Route path="/about" component={About} />
<Route path="/" exact component={Home} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
}
export default App;
// src/pages/Login.jsx
import LoginButton from "../components/LoginButton";
export default function Login() {
return (
<div>
<h2>Login 페이지</h2>
<LoginButton />
</div>
);
}
// src/components/LoginButton.jsx
import { withRouter } from "react-router-dom";
export default withRouter(function LoginButton(props) {
console.log(props);
function login() {
setTimeout(() => {
props.history.push("/");
}, 1000);
}
return <button onClick={login}>로그인하기</button>;
});
6. Redirect
// src/App.js
import { BrowserRouter, Redirect, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
import Login from "./pages/Login";
import Links from "./components/Links";
import NavLinks from "./components/NavLinks";
const isLogin = false;
function App() {
return (
<BrowserRouter>
<Links />
<NavLinks />
<Switch>
<Route
path="/login"
render={() => (isLogin ? <Redirect to="/" /> : <Login />)}
/>
<Route path="/profile/:id" component={Profile} />
<Route path="/profile" component={Profile} />
<Route path="/about" component={About} />
<Route path="/" exact component={Home} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
}
export default App;
댓글남기기