React Router(리액트 라우터) - 3

Jonghan·2020년 4월 26일
1

react

목록 보기
4/5

SubRoute

여태까지의 방법으론 localhost:3000/about과 같이 한 단계를 진입하는데는 문제가 없었다. 하지만 요즘 URL들이 워낙 복잡한건 다들 알고 있을 것이다. localhost:3000/about만 해도 localhost:3000/about/policy localhost:3000/about/contact 등등 여러 URL로 나뉘어 있는 경우도 파다하다.

서브 라우트는 이럴때 사용하고, 라우트 내부에 또 라우트를 정의하는 것을 말한다.

지난 시간에 정의했던 User를 다시 가져와보자.

import React from 'react';
import qs from 'qs';

const users = {
  pkbird: {
    name: '비빔면',
    age: 25,
  },
  fahrenheit: {
    name: '화씨',
    age: 12,
  },
};
const User = ({ match, location }) => {
  const { userid } = match.params;
  const queryData = qs.parse(location.search, { ignoreQueryPrefix: true });
  console.log(queryData);
  const user = users[userid];
  if (!user) return null;
  return (
    <div>
      <b>{user.name}</b> ({user.age})
    </div>
  );
};

export default User;

URL에 따라 자신에게 오는 URL 파라미터와 쿼리를 처리하고 유저이름과 나이를 출력하는 컴포넌트이다.

Users.js파일을 만들고 다음같이 적어본다.

import React from 'react';
import { Link, Route } from 'react-router-dom';
import User from './User';

const Users = () => {
  return (
    <div>
      <h3>유저</h3>
      <ul>
        <li>
          <Link to="/users/pkbird">pkbird</Link>
        </li>
        <li>
          <Link to="/users/fahrenheit">fahrenheit</Link>
        </li>
      </ul>

      <Route path="/users" exact render={() => <div>유저를 선택하세요.</div>} />
      <Route path="/users/:userid" component={User} />
    </div>
  );
};

export default Users;

이런식으로 직접 유저의 아이디를 URL 파라미터로 입력해주지 않아도, Link를 통해, 유저의 정보를 불러올 수 있도록 했다.

그 후 App.js를 다음처럼 바꾼다.

import React from 'react';
import About from './About';
import Home from './Home';
import { Route, Link } from 'react-router-dom';
import Users from './Users'; // 바뀐 부분

function App() {
  return (
    <div>
      <ul>
        <li>
          <Link to="/"></Link>
        </li>
        <li>
          <Link to="/about">어바웃</Link>
        </li>
        <li>
          <Link to="/users">조회</Link> // 바뀐 부분
        </li>
      </ul>
      <Route path="/" component={Home} exact />
      <Route path={['/about', '/hi']} component={About} />
      <Route path="/users" component={Users} /> // 바뀐 부분
    </div>
  );
}

export default App;

이렇게 Users 컴포넌트로 라우팅을 시키면, 조회링크를 클릭할 시, 아래처럼 화면이 나온다.

pkbirdfahrenheit링크는 users/pkbird users/fahrenheit로 라우트로 사용되고 있는 Users 컴포넌트 안에 또다시 Route를 정의하여, 깊숙히 들어갈 수 있게한다.

<Route path="/users" exact render={() => <div>유저를 선택하세요.</div>} />
<Route path="/users/:userid" component={User} />

이렇게하면 users만 입력하면 유저를 입력하란 글귀가 뜨고,
users/유저아이디 즉 저 링크 중 하날 클릭하면 URL 파라미터User컴포넌트에 전해지게 되고 그럼 링크마다 결과값인 유저이름과 나이가 다르게 보인다.

요약을 하면, 라우트로 사용되는 특정 컴포넌트 (위 경우는 Users)안에 또 다른 라우트를 사용할 때, 그것을 서브 라우트라고 부른다. 이렇게하면 User컴포넌트는 서브 라우트가 되고 라우트의 URL 파라미터를 사용할 수 있게 된다.

History

history객체는 라우트로 사용된 컴포넌트에 match, location과 함께 전달되는 props이다. 이 객체를 잘 사용하면 라우터 API를 호출할 수 있다.

그게 뭔데 X덕아

예를 들어, 로그인 후 화면 전환, 버튼 클릭시 뒤로 가기, 다른 페이지 이탈 방지 등에 활용한다.

history.goBack() 은 뒤로 가기 이다.

history.push('/')'/'주소로 라우트 한다.

history.block(message)는 페이지에 변화가 생기는 것을 캐치해 유저에게 질문을 던진다.

User 컴포넌트에서 렌더 작성하는 파트에 다음과 같이 적어본다.

    <div>
      <b>{user.name}</b> ({user.age})
      <button onClick={() => history.goBack()}>뒤로 가기</button>
    </div>

버튼을 추가해보는 것이다.

그럼 다음과 같이 뒤로 가기 버튼이 생기고 클릭하면

나는 Users 컴포넌트에서 눌렀기 때문에 /users로 되돌아가는 걸 볼 수 있다.

      <button onClick={() => history.push('/')}>홈으로</button>

뒤로 가기 버튼 밑에 다음같이 코드를 한 줄 더 추가해보자

그럼 홈으로 라는 글귀의 버튼이 생긴걸 알 수 있는데 클릭해보면,

홈으로 돌아가는 걸 볼 수 있다.

이런식으로 history를 활용해 뒤로가거나, 홈으로 가거나 등등을 조작할 수 있다.
위에서도 썼듯이 로그인이 되면 history.push를 통해 홈으로 가거나, block을 통해 현재 웹페이지에서 벗어나는 것을 막기 위한 경고 메시지 등을 띄워줄 수 있다.

withRouter

이번에 쓰일 withRouter는 은근히 앞으로 리액트 공부를 하면서 알게모르게 많이 보게 되는 녀석이다. 그래서 바짝 긴장... 까진 할 필요는 없지만 아무튼 잘 새겨서 보면 좋을 것 같다.

withRouterHoC인데, 이게 뭐냐면 Higher-order Component의 약자이다.
라우트로 사용된 컴포넌트가 아닌데도, match, location, history객체에 접근하게 해준다.

구현법은 단순하다.

import React from 'react';
import { withRouter } from 'react-router-dom';

const WithRouterSample = ({match, location, history}) => {
  return (
    <div>
      
    </div>
  );
};

export default withRouter(WithRouterSample);

이렇게 맨끝에 withRouter()추가해 컴포넌트를 감싸주면 된다.

이렇게만 해주면 해당 컴포넌트는 라우트로 사용되지 않는데도 불구하고 match, location, history를 다룰 수 있게 된다. 라우트로 사용되는 다른 컴포넌트에 같이 렌더링을 해서 이것저것 출력해보면 진짜로 그 라우트로 넘어간 댜앙한 객체들을 사용할 수 있게 된다.

하지만, 여기서 주의할 점이 한 가지 있다.

자신을 보여주고 있는 라우트 컴포넌트를 기준으로 match를 받는다.

이게 무슨 말이냐면, Users컴포넌트에 이 withRouter컴포넌트를 렌더링시키게 되면, Users컴포넌트의 match에는 유저에 대한 정보가 없기 때문에, params가 출력되지 않는다.

반면에, User컴포넌트에 넣게되면, /users/pkbird처럼 유저 아이디라는 params를 받아오기 때문에, params가 출력된다. 따라서 withRouter를 쓸 경우, 어디에 넣어야 params를 제대로 받아올 수 있는지에 대한 고민을 꼭 해봐야 한다.

Users에 넣든 User에 넣든 화면에 그 컴포넌트가 렌더링 되는건 매 한가지지만, params 를 받아올 수 있느냐 없느냐는 큰 차이가 있다.

쓰고보니 너무 대충 쓴거 같은데.. 사실 길게 다루고 자시고 할 게 없긴 하다.
나중에 좀 실제로 어떤식으로 사용하는지 다룰 시간이 있으면 좋을것 같은데 장담은 못하겠네.

Switch

여러 Route를 감싸서, 그중 일치하는 하나의 라우트만 렌더링 시켜준다.
이건 왜 쓰냐하면, Not Found에 대한 처리를 하기 위해서 주로 쓰인다.
예를 들어, users/pkbird 이런건 라우트가 잘 되어있다. 올바르게 동작한다.

하지만 쌩뚱맞게 id/hihihi 이런 URL을 넣게되면 여기에는 아무런 정보도 들어있지 않다.

그런데도 불구하고, 위처럼 홈, 어바웃, 조회를 출력한다.
왜냐면, 저건 라우트가 아니고 링크로 적혀있는거기 때문에 URL과 상관없이 출력된다.

        <li>
          <Link to="/"></Link>
        </li>
        <li>
          <Link to="/about">어바웃</Link>
        </li>
        <li>
          <Link to="/users">조회</Link>
        </li>

하지만, 나는 화면에 너가 지금 잘못된 주소로 들어왔다는 걸 보여주고 싶다.
그럴때는, SwitchRoute들을 감싸고, 다음과 같이 처리한다.

      <Switch>
        <Route path="/" component={Home} exact />
        <Route path={['/about', 'hi']} component={About} />
        <Route path="/users" component={Users} />
        <Route
          render={({ location }) => (
            <div>
              <h2>Not Found 404</h2>
              <p>{location.pathname}</p>
            </div>
          )}
        />
      </Switch>

이미 들어가있는 /, /about, /hi, /users를 뺀 나머지를 URL로 입력할 경우, 전부 다음과 같이 출력된다.

위에 링크들마저 안뜨게 하려면, 다른 조치가 필요해보이지만.. 귀찮으니 알아보진 않겠다.

여기까지 라우트의 거의 모든 것을 다뤄봤다.
그럼 끄읕~

profile
열정적으로 살고 싶다.

0개의 댓글