본문으로 바로가기

react-router-dom v5

category React, Next, Redux/⚛ React.JS 2020. 2. 29. 20:09
 

react-router

Declarative routing for React

www.npmjs.com

 

React Router: Declarative Routing for React

Learn once, Route Anywhere

reacttraining.com


 

react-router에는 다양한 컴포넌트들이 있는데 그 중에서 우리는 일단 react-router-dom만 사용해보도록하자

npm install react-router-dom

react-router-dom 모듈에서 주로 사용하는 건 HashRouter, BrowserRouter, Router, Link, Switch, Redirect, withRouter, useParams(rrd에서 제공하는 4개의 훅 중 하나) 등이다.

 

Router들 (HashRouter, BrowserRouter)는 URL을 구동하게 만들어준다. Hash 쪽은 static하게 프론트만 있을 때 주로 사용하고 BrowserRouter는 서버 사이드 렌더링이 존재할 때 주로 사용한다. 

 

이 아래 설명된 속성들은 모두 Router (HashRouter, BrowserRouter) 안에 있어야만 작동한다는 게 포인트다.

 

Route는 해당 path로 이동 및 컴포넌트를 실행한다. 

 

Switch는 해당 태그 안에 든 Route 중 하나에만 접속하게 해준다.

 

withRouter는 다른 컴포넌트와 연결하여 props를 전달하기 위해 사용된다

 

Link는 a태그와 비슷한 역할을 하지만 상태를 유지하면서 페이지를 전환하게 해줍니다. a태그로 움직이면 아예 화면을 새로 렌더링하게 되는 거니까 SPA 를 쓸 이유가 없어지죠!

 

useParams는 일종의 훅이다. url 정보들을 가져올 수 있다. withRouter를 사용해서 match에서 정보를 가져오는 방법도 있지만 useParams을 활용해서 간단한 정보를 가져오는게 더 빠르고 쉬울 때가 있다.

 

Redirect는 말 그대로 리다이렉트한다. <Redirect from="*" to="/" />의 경우 모든 곳에서 /로 리다이렉트 함을 의미함.

 

🚀 라우팅 설정을 할 때 exact를 잘 사용해야 한다. exact는 정확하게 그 경로로 접속해야만 렌더한다는 의미이다. 아래 코드의 경우 /tv에 exact를 주었다. 이 경우 /tv/popular로 접속할 경우 /tv는 렌더링되지 않는다.
최상위 경로인 / 경우에는 exact를 하지 않으면 모든 경우에서 다 실행된다. 경우에 따라 exact를 잘 사용하자.

 

 

이들을 사용해서 간단하게 라우팅 설정을 해보자

 

// header 컴포넌트. styled-component를 적용했습니다.

export default withRouter(({ location: { pathname } }) => (
  <Header>
    <List>
      <Item>
        <SLink to="/">Movie</SLink>
      </Item>
      <Item>
        <SLink to="/tv">TV</SLink>
      </Item>
      <Item>
        <SLink to="/search">Search</SLink>
      </Item>
    </List>
  </Header>
));
// routes.js

import React from "react";
import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
import Home from "../Routes/Home";
import TV from "../Routes/TV";
import Search from "../Routes/Search";
import Header from "./Header";

export default () => (
  <BrowserRouter>
    <Header /> // Link가 있기 때문에 반드시 router 내부에 있어야 한다
    <Switch>
      // Route가 지정한 component에는 자동으로 위치에 대한 props가 주어진다.
      <Route path="/" exact component={Home} />
      <Route path="/tv" exact component={TV} />
      <Route path="/tv/popular" render={() => <h1>Hello guys</h1>} />
      <Route path="/search" component={Search} />
      <Redirect from="*" to="/" />
    </Switch>
  </BrowserRouter>
);
// App.js

import React from "react";
import Router from "./Router"; // router.js를 import함
import Header from "./Header";

class App extends React.Component {
  render() {
    return (
      <>
        <Router />
      </>
    );
  }
}

export default App;

 

 

tip) <></>는 아무 내용도 없는 것이 아니라 Fragments라 하여 여러개의 컴포넌트를 사용할 수 있게 해준다. 상당히 자주 쓰이므로 알아두자

 

export할 때 다음과 같이 withRouter() 내부로 전달하면 해당 컴포넌트는 props를 가져가기 때문에 유용하다

import { Link, withRouter } from "react-router-dom";

export default withRouter(({ location: { pathname } }) => (
  <Header>
    <List>
      <Item current={pathname == "/" ? true : false}>
        <SLink to="/">Movies</SLink>
      </Item>
    </List>
  </Header>
));

 

Route를 통해 경로로 접근할 수 있는 컴포넌트에서 withRouter로 감싸주면 이용할 수 있는 props를 추출해보았다. 크게 history, location, match로 이루어져 있다. 뒤로가기나 앞으로가기 함수도 들어있으므로 유용하게 처리할 수 있다. 이 객체는 Route가 지정한 component들에는 자동으로 들어있다. 예를 들어 <Route path="/tv" component={TV}>의 경우 TV component 다음 props를 자동으로 가진다.

 

강제로 이동시키는 history의 push나 match의 path, url, params 등이 자주 이용된다.

 

 

 

history, location, match 와 같은 props를 이용해 리다이렉션을 줄 수도 있다.

다음 코드는 history의 push 메서드를 이용해 팅겨낸 것이다.

props.history.push("/");

 

이것 외에도 go, goback, replace 등 다양한 메서드가 있으므로 활용하면 된다.

 

자세한 건 문서를 살펴보자.

(https://reacttraining.com/react-router/web/api/history)

 

 

 

추가!

 

* Route에 여러 path 지정하기 (v5 부터 가능)

 

/about, /info로 접근 시 About 컴포넌트를 렌더한다.

<Route path={["/about", "/info"]} component={About} />

 

* param 넣기

<Route path="/profile/:username" component={Profile} />

 

* 쿼리 처리하기

 

location의 serach 부분에 쿼리의 내용이 들어 있습니다. 따로 Route에서 처리하는 방법은 없고, 가까운 param을 렌더하는 컴포넌트에서 location.search를 가져와서 파싱한 다음에 사용하면 됩니다.

 

http://localhost:3000/about?detail=true&another=1

 

 

해당 문자열을 수작업으로(!) 분리할 수도 있겠지만 쿼리 문자열을 객체로 변환하는 qs 라이브러리를 사용합시다.

파싱한 이후에는 원해는 대로 사용하시면 됩니다.

 

npm i qs
import React from "react";
import qs from "qs";

function About({ location }) {

  // qs의 parse를 이용합니다. 뒤의 옵션은 ?를 제거한다는 의미입니다
  const query = qs.parse(location.search, { ignoreQueryPrefix: true });

  console.log(query);
  return (
    <div>
      <h1>소개</h1>
      <p>리액트 라우터 실습</p>
      {query.detail === "true" && <p>detail을 true로 주셨습니다</p>}
    </div>
  );
}

export default About;

 

* 404 페이지

 

<Swtich>
  <Route render={() => <div>없는 페이지입니다</div>} />
</Swtich>

 

 

 


 

참고로, () => () 와 () => {} 는 같은 것이되 후자는 return을 요구한다는 점만 다르다.

 

() => (<div></div>)
() => {return <div></div>}

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체