React Router

박진·2021년 3월 26일
0

React Router를 마스터해보자.

router를 하기전에 새로운 파일을 만들어 보자 React template를 미리 만들어놓으면 복사해서 써주면 아주 간편하기에 만들어놓는것을 추천한다. 복사하는 방법은

cp -R [복사할 폴더 or 파일][만들파일 or 폴더]

설치

npm install react-router-dom

이지하다 좋은 스타트이다.

이제 라우팅을해보자

여기서 라우팅이란?

사용자가 어떤 주소로 들어왔을때, 그주소에 해당하는 적당한 페이지를 사용자에게 전해주는것을 라우팅 또는 라우터라 한다.

자 그렇게 설치가 끝이 났으면 import를 해주자.

import {BrowserRouter, Route} from 'react-router-dom';

BrowserRouter, 이친구는 최상위 컴포넌트이다.

그래서 만약 App이 기준컴포넌트라면

이런식으로 감싸주면된다.

Url에 따른 적당한 컴포넌트가 잘위치하게 도와주는 친구는 Route

<BrowserRouter>
<App/>
</BrowserRouter>
function App() {
  const name = "jin";
  return (
    <div>
      <h1>React Router</h1>
      <ul>
        <li>
          <a href="/">Home</a>
        </li>
        <li>
          <a href="/about">About</a>
        </li>
        <li>
          <a href="/contact">contact</a>
        </li>
      </ul>
      <Route path="/">
        <Home />
      </Route>
      <Route path="/about">
        <About />
      </Route>
      <Route path="/contact">
        <Contact />
      </Route>
    </div>
  );
}

export default App;

이런식으로 route에게 이동하고 싶은 path를 설정해주면된다.

클릭시, 클릭한 컴포넌트가 보이게 된다. 캬~

근데 여기서 중요한게 있다. 나는 contact를 클릭했는데, home하고 contact가 같이보이게 된다.

왜그러는것일까?

그 이유는

www.good.com/
www.good.com/contact

나의 홈의 path는 "/" contact의 path는 "/contact" 이다 이렇게되면 contact를 클릭시에 / 인 home에도 걸리게되고 contact에도 같이 걸리게된다.

해결법은 exact를 넣는것이다.

      <Route exact path="/">
        <Home />
      </Route>

이렇게만 exact만 넣어주면 그것에 정확히 맞는 것만 매칭해주기때문에 이러한 문제를 개선할수있다.

exact와 비슷한 효과를 낼수있는게 있는데, 그것은 switch이다. 하지만, 조금 다르기에 일단은 봐보자. 우선 switch도 import해주자

import {BrowserRouter, Route, Switch} from 'react-router-dom';
      <Switch>
        <Route path="/">
          <Home />
        </Route>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/contact">
          <Contact />
        </Route>
      </Switch>

여기서 switch 로 감싸게되면 path와 일치하는 첫번째 컴포넌트를 발견하면 나머지 컴포넌트를 버린다. 따라서 여기서 exact가없으면 모두 / 가 걸려서 home이외의 나머지는 클릭을해도 출력이되지않는다.

      <Switch>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/contact">
          <Contact />
        </Route>
        <Route path="/">
          <Home />
        </Route>
      </Switch>

그런데 만약에 home을 가장 밑으로 놓게되면 클릭시에 /이 마지막에 중복이되어서 하나클릭해도 모두 이동이 가능하게되어진다.

이러한 스위치의 특징을 이용하면 사용자가 잘못된 페이지에 접속시에 Not found라는 메시지를 출력할수있게된다.

      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/contact">
          <Contact />
        </Route>
        <Route path="/">Not found</Route>
      </Switch>

그런데, react의 장점인 싱글페이지에서 새로운 컴포넌트가 리로드될때 새로고침없이 보여주는 위해서는 link를 사용해야한다.

import { BrowserRouter, Route, Switch, Link } from "react-router-dom";

또 Link를 import해주고, 기존의 a태그를 Link태그로 변경하고, href를 to로 변경해주면 끝이다. 이제 리로드가 새로고침없이 되는것을 확인할수있다. 캬 정말 간편하고 좋다.

        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
        <li>
          <Link to="/contact">contact</Link>
        </li>

여기서 잠깐,

웹서버를 설정할때 어떤 path로 들어오던간에 root페이지에있는 html파일을 서비스할수있다면
BrowserRouter를 써야하고 그게안된다면 HashRouter를 쓰면된다.

import {HashRouter} from 'react-router-dom';

HashRouter는 대신에 url주소에 /#/ 이런식으로 #이 추가되는데 브라우저는 #를무시하기에 괜찮지만 깔끔하지는 않다.

다시 Link에 살짝 부가적인 기능이있는 Link가있는데,

NavLink이다

import {BrowserRouter, Route, Switch, NavLink} from 'react-router-dom';

클릭시에 a태그에 active라는 class가 형성되는게 보인다.

와 진짜 편하다. 이것을 이용하면, 사용자가 자신이 위치한곳을 쉽게 보여줄수있다. 엄청나다.

재밌는점은 router안에 router가 중복되서도 작동이될수있는데

만약에 about안에 switch와 Route를 이용해서 아래와 같이 만들면

        <li>
          <NavLink to="/about">
            <h2>About</h2>
            <ul>
              <li>
                <NavLink to="/about/1">About 1</NavLink>
                <NavLink to="/about/2">About 2</NavLink>
                <NavLink to="/about/3">About 3</NavLink>
              </li>
            </ul>
            <Switch>
              <Route path="/about/1">about1 입니다</Route>
              <Route path="/about/2">about2 입니다</Route>
              <Route path="/about/3">about3 입니다</Route>
            </Switch>
          </NavLink>
        </li>

이런식의 결과를 만들수도있다.

그런데 페이지가 이런식으로 몇개밖에없을때는 이런식으로 하면되지만, 우리가 작업할 페이지가 수없이 많을때에는 배열을 만들어 자동으로 리스트와 라우터를 만들면된다.

class App extends Component {
  state = {
    lis: [],
  };

  hey = () => {
    const contents = [
      { id: 1, title: "ok", description: "hello" },
      { id: 2, title: "ok", description: "hello" },
      { id: 3, title: "ok", description: "hello" },
    ];

    this.setState({
      lis: contents,
    });
  };

  componentDidMount() {
    this.hey();
  }

  render() {
    const { lis } = this.state;

    return (
      <div>
        <h1>React Router</h1>
        <ul>
          <li>
            <NavLink to="/">Home</NavLink>
          </li>
          <li>
            <NavLink to="/about">
              <h2>About</h2>
              <ul>
                {lis.map((newlist) => (
                  <NavLink to={`/about/${newlist.id}`}>
                    <About
                      key={newlist.id}
                      title={newlist.title}
                      description={newlist.description}
                    ></About>
                  </NavLink>
                ))}
              </ul>
              <Switch>
                <Route path="/about/1">about1 입니다</Route>
                <Route path="/about/2">about2 입니다</Route>
                <Route path="/about/3">about3 입니다</Route>
              </Switch>
            </NavLink>
          </li>
          <li>
            <NavLink to="/contact">contact</NavLink>
          </li>
        </ul>
import React, { Component } from "react";

class About extends Component {
  render() {
    console.log(this.props);
    return (
      <li>
        About
        <h2>{this.props.title}</h2>
        <p>{this.props.description}</p>
      </li>
    );
  }
}

export default About;

이런식으로 작성하게되면

이런식으로 배열로 리스트를 작성했을때 하나의 route로 이동하는 방법이있는데,

   <Route path="/about/:about_id">
      <About></About>
    </Route>

이런식으로 Route path안에 :about_id 로 이동되어질 값만 입력해주면끝이다.

이외의 hook을이용한 useParams도 있고 더욱 많은 api들이있다 더욱더 알아봐서 더 좋은 서비스를 만들어보자.

profile
Hello :)

0개의 댓글