출처

해당 내용은 ZeroCho님의 리액트 무료 강좌 중 ReactRouter를 정리한 내용입니다.

코드 : https://github.com/ZeroCho/react-webgame/tree/master/react-router

포인트

  • 웹사이트 개발시 역할
  • React에서의 역할
  • React 연동방법
  • 그 외 정보는 공식 문서 참고

React Router 도입하기

설치

npm i react-router​
  • react-router 뼈대. 웹, 앱 둘다 사용 가능
npm i react-router-dom
  • 웹에서 사용할 때 설치.
  • 실제로는 react-router-dom만 사용
  • react-router는 react-router-dom이 내부적으로 사용

Router 컴포넌트

Router 컴포넌트를 사용하면 각각 따로만들었던 컴포넌트를 하나의 페이지에서 동시에 사용 가능하다.

컴포넌트의 최상위를 <..Router>로 감싸줘야한다.

  • Route : 페이지들 만듬
  • path : 페이지 주소
  • component : 보여줄 컴포넌트
const Games = () => {
    return (
        <BrowserRouter>
            <div>
                <Route path="/3_NumberBaseball" component={NumberBaseball}></Route>
                <Route path="/5_leture" component={RSP}></Route>
                <Route path="/6_lecture" component={Lotto}></Route>
            </div>
        </BrowserRouter>
    );
}

Link와 BrowserRouter

실제로 페이지가 여러 개가 있는게 아니라 react-router만 알고있는 가상으로 만들어낸 페이지이다.

페이지 전환처럼 보이기 위해서 Link 컴포넌트를 사용한다.

<Link to='/number-baseball'>숫자야구</Link>
  • Route로 정의한 path를 to에 넣어준다.
  • html의 <a></a>와 동일한 기능이다.
링크 클릭시 'http://localhost:8080/lotto-generator'로 주소가 바뀐다.
 

배치

공통적인 layout은 `<Route>` 바깥으로 빼야한다.

<BrowserRouter>
  <div>
    <Link to='/number-baseball'>숫자야구</Link>
    &nbsp;
    <Link to='/rock-scissors-paper'>가위바위보</Link>
    &nbsp;
    <Link to='lotto-generator'>로또생성기</Link>
  </div>
  <div>
    <Route path="/number-baseball" component={NumberBaseball} />
    <Route path="/rock-scissors-paper" component={RSP} />
    <Route path="/lotto-generator" component={Lotto} />
  </div>
</BrowserRouter>
이렇게 배치할 경우
  • 첫번째 div에 있는 부분은 페이지가 변경되도 바뀌지 않는다.
  • 두번째 div에 있는 부분은 페이지가 변경되면 바뀐다.

해시 라우터, params, with Router

해시 라우터

해시 라우터 사용시 링크를 클릭하면 주소 중간에 #가 들어간다.

  • ex) http://localhost:8080/#/number-baseball

장점 : 새로고침을 해도 화면이 보인다.

단점 : 서버가 해석하지 못해서 실무에서는 잘 사용되지않는다. 서버가 해석하지 못하면 검색 엔진에 뜨지 않는다.

  • url에 #가 있으면 서버가 해석하지 못하고, 브라우저(프론트엔드)에서 처리한다.
  • 검색엔진에 뜨게하려면 따로 서버에 세팅해야한다.

 

 

 

 

따라서 주소 이상해도 되고, 검색 엔진에 뜨지 않아도 되면 사용해도 된다.

dynamic Route matching1

Route가 계속 추가되면 추가해야할 만큼 일일히 쳐줘야한다. => 너무 방대해짐

route가 늘어나는 것을 하나로 합칠 수 있다.

효율적으로 Route들을 관리 가능

param

:는 param이라고 불린다.

/game/으로 시작하는 모든 Link는 <Route path="/game/:name >" 하나로 매칭할 수 있다.

ex)<Route path="/game/:name >"로 선언한 경우

  • name부분은 동적으로 변경된다.
    • <Link to="/game/...">
      • ...은 아무거나
      • /game/으로 시작하는 모든 Link가 이 Route에 매칭된다.

withRouter

<Route>내 정의된 component에서 this.props에는 자동으로 history, location, match가 생기며, 이는 <Route>가 자동으로 넣어주는 것이다.

<Route>와 연결이 안된 컴포넌트에서 history, location, match를 사용하고 싶으면 withRouter를 사용하면 된다.

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

class GameMatcher extends Component {}

export default withRouter(GameMatcher);

location, match, history

history

페이지 넘나든 내역을 가지고있다. 라우터 이동에 사용하며, goBack, goForward... 함수를 사용할 수 있다.

내부적으로 브라우저의 history를 사용한다.

기본 브라우저의 동작과 달리 실제로 페이지가 바뀌는게 아니기 때문에 히스토리를 관리할 수 있는게 존재한다.

match

동적 주소 라우팅시 params정보가 존재

match > params에 param 정보가 들어있다. 이걸로 분기처리를 할 수 있다.

location

주소(pathname), hash, search가 들어있다. 나중에 배움.

dynamic Route matching2

this.props.match.params.name를 이용해 분기 처리

하나의 라우터로 여러개의 페이지를 처리

class GameMatcher extends Component {
  render() {
    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 === 'lottoe-generator') {
      return <Lotto />
    }
    return (
      <div>
        일치하는 게임이 없습니다.
      </div>
    );
  }
}

queryString과 URLSeatchParam

queryString

<Link to="">에 ?붙이고 key=value형식으로 정의하는 것

여러개일경우 &로 구분

주소로 데이터를 전달하는 가장 쉬운 방법

ex) <Link to='/game/number-baseball?query=10&hello=zerocho&bye=react'>

이 정보는 <Route>내 정의된 component에서 this.props.location.search에 쿼리스트링이 존재한다.

URLSeatchParam

queryString을 편하게 파싱하기 위해 사용한다.

브라우저에서 제공.

let urlSearchParams = new URLSearchParams(this.props.location.search.slice(1)); console.log(urlSearchParams.get('hello'));

render props, switch, exact

하위 컴포넌트로 props 넘기는 방법

첫 번째 방법 : 함수로 감싸기

<Route path="/game/:name" component={() => <GameMatcher props="12345" />} />

두 번째 방법 : render를 사용해 부모의 props 넘기기

<Route path="/game/:name" render={(props) => <GameMatcher props={props} />} />

=> props를 그대로 넘기는 게 목적이면 2번 방법을 추천.

동시에 라우트가 여러 개 뜨는 것을 막아보자.

switch

<Route>가 동적 라우팅과 정적 라우팅이 같이 있을 때 정적 라우팅으로 접근하면 화면이 어떻게 나올까?

ex) /game/exact로 접근시 두 라우터가 모두 렌더링된다.

<BrowserRouter>
    <div>
        <Route path="/game/:name" component={GameMatcher} />
        <Route path="/game/exact" component={GameMatcher} />
    </div>
</BrowserRouter>

이를 개선하기 위해 <Switch>를 사용하면 첫번째로 렌더링되는 것 하나만 렌더링한다.

<BrowserRouter>
    <div>
        <Switch>
            <Route path="/game/:name" component={GameMatcher} />
            <Route path="/game/exact" component={GameMatcher} />
        </Switch>
    </div>
</BrowserRouter>

exact

<Route>에 매칭되는 라우터가 여러 개일 때는 매칭되는 라우터가 모두 렌더링된다.

  • 기본적으로 상위주소도 항상 일치한다고 생각한다.

ex) /game/number-baseball로 접근시 두 라우터가 모두 나온다. => /도 일치한다고 생각한다.

<BrowserRouter>
    <div>
        <Route path="/" component={GameMatcher} />
        <Route path="/game/:name" component={GameMatcher} />
    </div>
</BrowserRouter>

이런 경우, <Switch>로도 해결이 되지 않는다.

  • 위의 경우 /가 더 위에 있기때문에 / 라우트만 렌더링된다.
  • 원래 원하는 건 아래 라우트로 렌더링되는 것.

exact를 사용해 적힌 주소와 정확히 일치하는 라우트만 렌더링한다.

그래서 아래의 경우 /에 붙여서, 진짜 주소가 /인 경우만 렌더링되게한다.

<BrowserRouter>
    <div>
        <Switch>
          <Route exact path="/" component={GameMatcher} />
          <Route path="/game/:name" component={GameMatcher} />
        </Switch>
    </div>
</BrowserRouter>

'React' 카테고리의 다른 글

Quick Start  (0) 2022.09.24
React  (0) 2022.07.22
React - Redux : initialState: undefined 에러 해결  (0) 2022.03.28

+ Recent posts