react-router-dom v5리액트 기초/Routing2021. 7. 22. 03:39
Table of Contents
react-router-dom v5
- 아래 명령어를 통해 react-route-dom을 설치하고 여기를 들어가서 공식문서를 확인해보자.
npm i react-router-dom@5.3.0
- 아래 순서를 따라서 라우팅을 처리하자.
1. index.js에 BroweserRouter 적용하기
- BrowserRouter는 웹 브라우저가 가지고 있는 주소 정보를 props로 넘겨주는 역할을 한다.
- 현재 내가 어느 주소를 보고 있는 지 쉽게 알려준다.
index.js
import React from 'react';
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// 이부분이 index.html에 있는 div#root에 우리가 만든 컴포넌트를 실제로 랜더링하도록 연결해주는 부분.
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
reportWebVitals();
2. 세부 화면 만들기
- App.js에서 주소에 따라 이동할 화면(컴포넌트)를 작성하자.
- 나는 Home, Duck, Poodle 세개의 컴포넌트를 작성할 것이다.
Home.js
import React from 'react';
const Home = () => {
return(
<h1>Home 화면!</h1>
);
}
export default Home;
Duck.js
import React from 'react';
const Duck = (props) => {
return (
<div>
<h1>Duck 화면!</h1>
<h1>이름은 {props.name}</h1>
</div>
);
}
export default Duck;
Poodle.js
import React from 'react';
const Poodle = () => {
return(
<h1>Poodle 화면!</h1>
);
}
export default Poodle;
3. App.js에 Route 적용시키기
- Route를 적용시키기 위해서 App.js에서 Route를 임포트해야 한다.
import { Route } from "react-router-dom";
- Route를 처리하는 방법은 넘겨줄 props가 없을 때와 있을 때 두가지가 있다.
Route?
라우트로 설정한 컴포넌트는, 3가지의 props 를 전달받는다:
- history - 이 객체를 통해 push, replace 를 통해 다른 경로로 이동하거나 앞 뒤 페이지로 전환 할 수 있다.
- location - 이 객체는 현재 경로에 대한 정보를 지니고 있고 URL 쿼리 (/about?foo=bar 형식) 정보도 가지고있다.
- match - 이 객체에는 어떤 라우트에 매칭이 되었는지에 대한 정보가 있고 params (/about/:name 형식) 정보를 가지고있다.
- 넘겨줄 props가 없을 때
<Route path="주소[원하는 주소]" component={[보여줄 컴포넌트]}/>
만약 /duck 주소에 Duck 컴포넌트를 보여주고 싶으면 아래처럼 작성하자.
<Route path="/duck" component={Duck}/>
+++ 변경사항!!!!
- react-router-v6부터 아래처럼 Routes 컴포넌트로 Route를 감싸고 element prop에 컴포넌트를 넘겨줘야 한다!!
<Routes>
<Route path="/" element={<Uploader/>} />
</Routes>
- 넘겨줄 props가 있을 때 (중요!!!)
<Route path="주소[원하는 주소]" render = {(props) => (<[컴포넌트] [props]={[넘겨줄 데이터]}/>)}/>
- 만약 /duck 주소에 props로 name이라는 데이터를 넘기고 Duck 컴포넌트를 보여주고 싶으면 아래처럼 작성하자.
- 만약 props로 값을 넘겨주면 history, match, location 객체가 덮어 씌워지므로 props를 받는 Route 컴포넌트에 아래처럼 {...props}를 넘겨줘야 한다!
<Route path="/duck" render = {(props) => (<Duck name={name} {...props}/>)}/>
- 위에서 만든 화면들을 App.js 파일에서 Route 처리를 해서 실행을 해보자.
App.js
import './App.css';
import { Route } from "react-router-dom";
import Duck from "./Duck";
import Home from "./Home";
import Poodle from "./Poodle";
import {useState} from 'react';
const App = () => {
const [name, setName] = useState('Duckgugong');
return (
<div className="App">
<Route path="/" component={Home}/>
<Route path="/duck" render = {(props) => (<Duck name={name}/>)}/>
<Route path="/poodle" component={Poodle}/>
</div>
);
}
export default App;
http://localhost:3000
http://localhost:3000/duck
http://localhost:3000/poodle
- /duck과 /poodle 주소를 입력했을 때 나타나는 화면에 / 주소를 입력했을 때 보이는 Home 컴포넌트가 중복으로 보이는 모습을 볼 수 있다!
- "/' 기호가 "/duck"과 "/poodle"주소에도 포함되어 있기 때문이다. 이를 해결하기 위해 exact를 추가하거나 <Switch>로 라우트를 감싸주자.
4-1. exact / <Switch> 적용하기 (exact)
- 라우트를 설정할 때 exact를 붙여주면 주어진 경로와 정확히 맞아 떨어져야만 설정한 컴포넌트를 보여준다.
<Route exact path="[정확히 입력했을 때만 컴포넌트를 보여줄 주소]" component={컴포넌트}/>
- 위의 예시의 경우 주소에 "/" 기호를 포함하기만 해도 Home 컴포넌트를 보여주므로 이 부분에 exact를 추가해서 다른 컴포넌트를 보여줄 때 중복적으로 나타나지 않게 만들자.
App.js
import './App.css';
import { Route } from "react-router-dom";
import Duck from "./Duck";
import Home from "./Home";
import Poodle from "./Poodle";
import {useState} from 'react';
const App = () => {
const [name, setName] = useState('Duckgugong');
return (
<div className="App">
<Route exact path="/" component={Home}/>
<Route path="/duck" render = {(props) => (<Duck name={name}/>)}/>
<Route path="/poodle" component={Poodle}/>
</div>
);
}
export default App;
localhost:3000
localhost:3000/duck
localhost:3000/poodle
4-2. exact / <Switch> 적용하기 (<Switch>)
- Switch로 Route를 감싸면 첫번째로 매칭되는 path를 가진 컴포넌트를 렌더링 시킨다.
- exact와 다른 점은 첫번째 매칭만 본다는 것! 그리고 반드시 '/' 경로에는 exact를 추가해야 한다!
- 잘못된 주소를 입력했을 때, 에러 페이지를 띄워서 처리할 수 있다.
- Switch를 사용하려면 임포트해서 사용해야 한다.
import './App.css';
import { Route, Switch } from "react-router-dom";
import Duck from "./Duck";
import Home from "./Home";
import Poodle from "./Poodle";
import PageNotFound from "./PageNotFound";
import { useState } from 'react';
const App = () => {
const [name, setName] = useState('Duckgugong');
return (
<div className="App">
<Switch>
<Route exact path="/" component={Home} />
<Route path="/duck" render={(props) => (<Duck name={name} />)} />
<Route path="/poodle" component={Poodle} />
<Route component={PageNotFound}/>
</Switch>
</div>
);
}
export default App;
잘못된 URL 처리
- 잘못된 url을 입력했을 때, pagenotfound 라는 문구를 띄우는 PageNotFound 컴포넌트를 만들어보자.
- 주소에 오류가 발생했을 때, path 값이 없는 Route를 만들어서 이를 처리할 수 있다.
- 하지만, 아래처럼 Switch로 감싸지 않고 path값이 없는 Route를 사용했을 때는 문제가 발생한다.
<Route exact path="/" component={Home} />
<Route path="/duck" render={(props) => (<Duck name={name} />)} />
<Route path="/poodle" component={Poodle} />
<Route component={PageNotFound}/>
- 만약 올바른 "duck" 경로에 접속을 해도 path 값이 없는 리액트의 라우터가 path를 매칭시킬 값이 없기 때문에 올바른 주소를 입력해도 렌더링된다.
- 잘못된 주소인 "duck123"에 접속해도 무조건적으로 렌더링이 발생한다.
- 즉, 경로값이 없는 Route는 어떠한 주소에도 렌더링된다.
- 이를 해결하기 위해서 Switch를 사용해서 라우터들을 감싸면 잘못된 경로를 입력했을 때만 에러페이지가 나타나도록 만들 수 있다.
<Switch>
<Route exact path="/" component={Home} />
<Route path="/duck" render={(props) => (<Duck name={name} />)} />
<Route path="/poodle" component={Poodle} />
<Route component={PageNotFound}/>
</Switch>
5. URL 파라미터 사용하기
- 웹사이트 주소에는 파라미터와 쿼리가 있다.
- 파라미터 의 경우엔 사용하기 전에 꼭 라우트에서 지정해야 하고 URL 쿼리의 경우엔 컴포넌트 내에서 동적으로 사용 할 수 있다.
- 파라미터는 라우팅 처리한 컴포넌트의 props의 match 객체에서 해당 정보를 확인할 수 있다. 이 객체에는 어떤 라우트에 매칭이 되었는지에 대한 정보가 있고 params (/about/:name 형식) 정보를 가지고있다.
- 쿼리는 라우팅 처리한 컴포넌트의 props의 location 객체에서 해당 정보를 확인할 수 있다.
이 객체는 현재 경로에 대한 정보를 지니고 있고 URL 쿼리 (/about?foo=bar 형식) 정보도 가지고있다.
- 파라미터
- 우선 App.js에서 Route를 설정하고 path 속성 값에서 주소 뒤에 : 를 붙여서 지정해야 한다.
<Route path="/[주소]/:[파라미터 키]" component={컴포넌트}/>
- 만약 /test 주소에 파라미터의 키 값을 hungry로 주고 이동할 컴포넌트를 Test이라고 하면 아래처럼 사용하면 된다.
<Route path="/test/:hungry" component={Test}/>
- 파라미터에 관한 정보는 Route를 설정한 컴포넌트의 props의 match 객체에서 확인할 수 있다.
- 아래처럼 App.js 와 Test.js를 작성한 후에 /test/chicken 주소에 접속해보자!
App.js
import './App.css';
import { Route } from "react-router-dom";
import Test from "./Test";
const App = () => {
return (
<div className="App">
<Route path="/test/:hungry" component={Test}/>
</div>
);
}
export default App;
Test.js
import React from 'react';
const Duck = (props) => {
console.log(props.match)
return (
<div>
<h1>Duck 화면!</h1>
</div>
);
}
export default Duck;
- props의 match객체에서 파라미터에 관한 정보를 확인할 수 있다!
- /test/chicken으로 접속하면 아래와 같이 match 객체에 대한 정보를 얻을 수 있다.
주의사항!
- 만약 아래처럼 파라미터로 라우터를 적용했을 때, /detail에 접속하면 아무 화면이 나타나지 않는다!
<Route path ="/detail:index" component={Detail}/>
- 파라미터를 이용해서 라우터를 적용하면 반드시 주소에 파라미터를 써줘야 원하는 컴포넌트가 화면에 나타난다!
6-1. 링크 이동 <Link/> or history (<Link/>)
- <Link/> 컴포넌트는 HTML 태그 중 a 태그와 비슷한 역할을 한다. <Link/>로 설정한 리액트 요소를 클릭하면 주소가 변경된다. 리액트 내에서 페이지 전환을 도와준다.
- Route와 마찬가지로 임포트해서 사용해야 한다.
- 기본 사용 형식은 아래와 같다.
<Link to="[주소]">[텍스트]</Link>
- <Link/>로 만든 리액트 요소를 클릭해서 주소를 변경하면 <Route/> 바깥에 있는 요소들은 주소가 변경되어도 변경되지 않는다!
App.js
import './App.css';
import { Route, Switch, Link } from "react-router-dom";
import Duck from "./Duck";
import Home from "./Home";
import Poodle from "./Poodle";
import PageNotFound from './PageNotFound';
import { useState } from 'react';
const App = () => {
const [name, setName] = useState('Duckgugong');
return (
<div className="App">
<div>
<Link to = "/">Home 화면으로</Link><br/>
<Link to = "/duck">Duck 화면으로</Link><br/>
<Link to = "/poodle">Poodle 화면으로</Link>
</div>
<div>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/duck" render={(props) => (<Duck name={name} />)} />
<Route path="/poodle" component={Poodle} />
<Route component={PageNotFound} />
</Switch>
</div>
<div>
<h1>Route 바깥!</h1>
</div>
</div>
);
}
export default App;
- 아래처럼 <Link/>로 주소를 변경시키면 Route로 설정한 리액트 요소 이외에는 변경되지 않는다!
6-2. 링크 이동 <Link/> or history (history 객체)
- Link 컴포넌트를 클릭하지 않고, 함수를 사용한 페이지 전환 방법이라고 볼 수 있다.
- App.js처럼 Router가 아닌 컴포넌트가 history 객체를 props로 받아와서 사용하기 위해서는 withRouter 임포트 한 후에 export 하는 부분의 컴포넌트를 withRouter로 감싸야 한다.
- withRouter는 Router가 아닌 컴포넌트에게 Router 특성을 부여한다.
- App.js 는 Router가 아닌 컴포넌트이기 대문에 history 객체를 사용하기 위해서 withRouter로 처리해야 한다!
import React from 'react';
// withRouter 임포트
import { withRouter } from "react-router";
const App = (props) => {
...
}
// 내보내는 부분에서 withRouter로 감싸준다.
export default withRouter(App);
- 혹은 history 객체를 useHistory리액트 훅으로 불러와서 사용할 수 있다.
import React from 'react';
import { useHistory } from "react-router-dom";
const App () => {
let history = useHistory();
...
}
사용법
props.history.push()
- push()안에 주소를 넣으면 해당 주소로 페이지를 이동시킨다.
- 훅 사용시 props.을 떼고 사용하면 된다.
props.history.goBack()
- 뒤로가기
- 훅 사용시 props.을 떼고 사용하면 된다.
버튼을 만든 후에 이벤트를 달아서 주소를 변경하게 해보자.
import './App.css';
import { Route, Switch, Link } from "react-router-dom";
import { withRouter } from 'react-router';
import Duck from "./Duck";
import Home from "./Home";
import Poodle from "./Poodle";
import PageNotFound from './PageNotFound';
import { useState } from 'react';
const App = (props) => {
const [name, setName] = useState('Duckgugong');
return (
<div className="App">
<div>
<Link to = "/">Home 화면으로</Link><br/>
<Link to = "/duck">Duck 화면으로</Link><br/>
<Link to = "/poodle">Poodle 화면으로</Link>
</div>
<div>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/duck" render={(props) => (<Duck name={name} />)} />
<Route path="/poodle" component={Poodle} />
<Route component={PageNotFound} />
</Switch>
</div>
{/*이벤트로 push(), goBack() 사용*/}
<div>
<button onClick={()=>{props.history.push("/duck");}}>/duck으로 이동</button>
<button onClick={()=>{props.history.goBack();}}>뒤로가기</button>
</div>
</div>
);
}
export default withRouter(App);
- 초기 화면
- /duck으로 이동 버튼 클릭 후
- 뒤로가기 버튼 클릭 후
7. 중첩 라우팅
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/info" component={Info} />
</Switch>
</BrowserRouter>
);
}
function Info() {
const { path } = useRouteMatch();
return (
<div>
<Switch>
<Route path={`${path}/detail`}>
<InfoDetail />
</Route>
</Switch>
</div>
);
}
'리액트 기초 > Routing' 카테고리의 다른 글
react-router-dom v6 (0) | 2022.06.08 |
---|---|
SPA/라우팅 (0) | 2022.06.03 |
history.push VS window.location.href (0) | 2021.08.06 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!