react-router

stella6767·2021년 8월 21일
0

React Tip

목록 보기
1/24
yarn add react-router-dom //CRA 없이는 react-router도 설치

리액트에서 페이지를 이동한다는 개념은 body의 내용이 바뀐다는 의미이다. 싱글 페이지 어플리케이션의 장점을 살리기 위해서는 a태그를 쓸 수는 있지만(새로고침됨) 안 쓰는 것이 좋다.

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root'), //index.html에 app을 랜더링
);

프로젝트에 리액트 라우터를 적용할 때는 index.js 파일에서 BrowserRouter라는 컴포넌트를 사용하여 감싸면 된다. 이 컴포넌트는 html5의 history api를 사용하여 페이지를 새로고침하지 않고도 주소를 변경하고, 현재 주소에 관련된 정보를 props로 쉽게 조회하거나 사용할 수 있도록 한다.

//Route 하나에 여러개 path 등록하기 

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

a태그 대신 Link 컴포넌트를 사용하여 다른 주소로 이동하기

<Link to="/about">소개</Link>
//페이지를 새로 불러오지 않고 html5 history api를 사용하여, 페이지의 주소만 변경

브라우저라우터 VS 해시라우터

ReactDOM.render(
  <React.StrictMode>
    <HashRouter>
      <App />
    </HashRouter>
  </React.StrictMode>,
  document.getElementById('root'), //index.html에 app을 랜더링
);

//새로고침해도 서버가 알아들어서 동작됨. 
//단점: 브라우저에서 검색엔진 로봇들이 돌아가면서 서버에 물어가먀, 정보를 수집하는데, 그 다음 링크들이
// 못 알아듣기 때문에 SEO에 불리. 실무에서 안 쓰임 

http://localhost:3000/#/...

주소 중간에 #이 들어간다. 이걸 해쉬라고도 부름

동적 라우터 매칭

라우터의 개수가 많아질 때 효율적으로 관리하기 위해서. :name 과 같은 param을 활용하여 분기시켜줄 수 있다. Router라는 컴포넌트에서 아래와 같이 GameMatcher라는 컴포넌트가 연결되어 있으면 history, location, match 라는 프로퍼티가 생기는데, 이를 활용해서 분기시킬 수 있다. 만약 라우트로 사용된 컴포넌트가 아닌 독립된 컴포넌트에서 이 프로퍼티를 사용하고 싶다면, HOC 패턴으로 withRouter로 묶어주면 된다.


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

const Games = () => {
  return (
    <BrowserRouter>
      <div>
        <Link to="/game/number-baseball">숫자야구</Link>
        &nbsp;
        <Link to="/game/rock-scissors-paper">가위바위보</Link>
        &nbsp;
        <Link to="/game/lotto-generator">로또생성기</Link>
        &nbsp;
        <Link to="/game/index">게임 매쳐</Link>
      </div>
      <div>
        <Switch>
          <Route path="/game/:name" render={(props) => <GameMatcher {...props} />} />
        </Switch> //요렇게 props를 넘겨줘도 된다.
      </div>
    </BrowserRouter>
  );
};

export default Games;

location, match, history

브라우저가 가지고 있는 history 객체 대신, 리액트 라우터 돔이 제공하는 history 객체를 사용해야 한다. 둘은 비슷하지만 다르므로 주의!!

라우터의 길이가 줄어둔 대신, 분기문이 길어졌다. 둘 중에 판단해서 사용하자.

쿼리스트링과 URLSearchParams

class GameMatcher extends Component {
  render() {
    let urlSearchParams = new URLSearchParams(this.props.location.search.slice(1));
    console.log(urlSearchParams.get('hello'));
    if (this.props.match.params.name === 'number-baseball') {
      return <NumberBaseball />
    } else if (this.props.match.params.name === 'rock-scissors-paper') {
      return <RSP />
    } else if (this.props.match.params.name === 'lotto-generator') {
      return <Lotto />
    }
    return (
      <div>
        일치하는 게임이 없습니다.
      </div>
    );
  }
}

export default GameMatcher;

url 파라미터: 특정 아이디 혹은 이름을 사용하여 조회할 때

/profiles/kang

쿼리: 키워드 검색용도거나 페이지에 필요한 옵션을 전달할 때.

/about?details=true

url 파라미터

파라미터는 라우트로 사용되는 컴포넌트에서 받아 오는 match 라는 객체 안의 params 값을 참조. match 객체 안에는 현재 컴포넌트가 어떤 경로 규칙에 의해 보이는지에 대한 정보가 들어있음

url 쿼리

쿼리는 location 객체에 들어있는 search 값에서 조회할 수 있습니다. search 값에서 특정 값을 읽어 오기 위해서는 이 문자열을 객체 형태로 변환해 주어야 함. 쿼리 문자열을 객체로 변환할 때는 qs라는 라이브러리를 사용

yarn add qs
//http://localhost:3000/about?detail=true

import qs from 'qs';

const About = ({ location }) => {
  const query = qs.parse(location.search, {
    ignoreQueryPrefix: true // 이 설정을 통하여 문자열 맨 앞의 ? 를 생략합니다.
  });
  const showDetail = query.detail === 'true'; // 쿼리의 파싱 결과값은 문자열입니다.
  return (
    <div>
      <h1>소개</h1>
      <p>이 프로젝트는 리액트 라우터 기초를 실습해보는 예제 프로젝트입니다.</p>
      {showDetail && <p>detail 값을 true 로 설정하셨군요!</p>}
    </div>
  );
};

숫자로 받아 와야 하는 경우면 parseInt 함수를 통해 꼭 숫자로 변환해 주고, 위처럼 논리 자료형 값을 사용해야 하는 경우에는 정확히 true 문자열이랑 일치하는지 비교

서브 라우트

라우트 내부에 또 라우트를 정의하는 것을 의미

그냥 라우트로 사용되고 있는 컴포넌트의 내부에 Route 컴포넌트를 또 사용하면 됨

라우트에서 컴포넌트 대신 render를 전달해서 보여주고 싶은 jsx를 넣어줄 수도 있다. 컴포넌트에 props를 별도로 넣어주고 싶을 경우 사용

jsx에서 props를 설정할 때 값을 생략하면 자동으로 true로 설정됨.

리액트 라우터 부가기능

history, match, location 객체

withRouter 함수는 hoc입니다. 라우트로 사용된 컴포넌트가 아니어도 match, location, history 객체를 접근할 수 있게 해 줍니다.

import { withRouter } from 'react-router-dom';
const WithRouterSample = ({ location, match, history }) => {
  return (
    <div>
      <h4>location</h4>
      <textarea
        value={JSON.stringify(location, null, 2)}
        rows={7}
        readOnly={true}
      />
      <h4>match</h4>
      <textarea
        value={JSON.stringify(match, null, 2)} //json에 들여쓰기가 적용된 상태로 문자열이 만들어짐
        rows={7}
        readOnly={true}
      />
      <button onClick={() => history.push('/')}>홈으로</button>
    </div>
  );
};

export default withRouter(WithRouterSample); //이렇게 감싸주면 됨

switch

동시에 Route가 여러개 뜨는 걸 방지하려면 switch 사용

switch 컴포넌트는 여러 Route를 감싸서 그 중 일치하는 단 하나의 첫번째 라우트만을 랜더링시켜 줌

switch를 사용하면 모든 규칙과 일치하지 않을 때 보여줄 not found 페이지도 구현할 수 있음.

Swtitch로도 불안하면 exact=true 를 사용하면 된다.

<Switch>
        <Route path="/" component={Home} exact={true} />
        <Route path={['/about', '/info']} component={About} />
        <Route path="/profiles" component={Profiles} />
        <Route path="/history" component={HistorySample} />
        <Route
          // path를 따로 정의하지 않으면 모든 상황에 렌더링됨
          render={({ location }) => (
            <div>
              <h2>이 페이지는 존재하지 않습니다:</h2>
              <p>{location.pathname}</p>
            </div>
          )}
        />
      </Switch>

NavLink

<ul>
        <li>
          <NavLink activeStyle={activeStyle} to="/profiles/velopert" active>
            velopert
          </NavLink>
        </li>
        <li>
          <NavLink activeStyle={activeStyle} to="/profiles/gildong">
            gildong
          </NavLink>
        </li>
      </ul>

Link와 비슷, 현재 경로와 Link에서 사용하는 경로가 일치하는 경우 특정 스타일 혹은 CSS 클래스를 적용할 수 있는 컴포넌트

profile
사수없는 개발자의 좌충우돌 성장기. 여기 적는 글들은 신뢰성 0%이므로 믿지 마세요!

0개의 댓글