분류 Reactjs

React Router 기초 : 단일 페이지 애플리케이션에서 라우팅

컨텐츠 정보

  • 조회 277 (작성일 )

본문

React Router에 대해 알아야 할 모든 것.


React는 단일 페이지 애플리케이션을 구축하기 위한 최고의 도구 중 하나로서 번성했습니다. 이는 제가 처음 React 앱을 구축하기 시작했을 때 상당히 이질적인 개념이었습니다. 그 당시 저는 사용자가 URL 경로에서 다른 경로로 리디렉션 할 때마다 별도의 웹 페이지를 제공한다는 개념에 익숙해졌고 처음에는 React가 탐색을 처리하는 방법을 머리로 감싸는 것이 다소 어려웠습니다.


이를 염두에 두고 이 블로그 게시물은 React 앱 내에서 가장 인기 있는 탐색 솔루션 중 하나인 React Router를 사용한 탐색의 기본 측면을 정리하고 설명하는 것을 목표로 합니다.


아래 첫 번째 섹션 전체에서 이 CodePen 예제를 참조하십시오.


링크, 스위치 및 라우터 


이 글의 서문에서 알 수 있듯이 React의 라우팅은 현재 제공되는 HTML, CSS 또는 JavaScript 리소스를 대체하거나 브라우저 콘텐츠를 다시 로드 하는 것을 포함하지 않습니다. 대신 react-router와 같은 라이브러리를 사용하면 현재 URL 위치에 따라 컨테이너를 동적으로 교체 할 수 있으며 이 모든 작업은 클라이언트 측에서 발생합니다. 이를 염두에 두고 React Router는 URL 경로를 기반으로 조건부 렌더링을 처리하는 래퍼로 더 일반적으로 이해할 수 있습니다.


이를 위해 개발자가 사용하는 기본 구성 요소는 <Route>, <Switch> 및 <Link>입니다. 다음 세 가지 구성 요소를 사용하는 기본 예제를 살펴 보겠습니다.


먼저 간단한 텍스트 구성 요소를 만들어 보겠습니다. 이러한 구성 요소는 탐색에서 실제 구성 요소를 교체 할 수 있는 스탠드 인입니다. HelloBanner는 간단한 메시지“Hello”를 포함하는 div이고 WorldBanner는“World!”를 포함합니다.


const HelloBanner: React.FunctionComponent = () => {
  return (
    <div id="banner_hello" className="banner">
      <span>Hello Banner is currently displayed. We are currently in path "/hello"</span>
    </div>
  ) 
}

const WorldBanner: React.FunctionComponent = () => {
  return (
    <div id="banner_world" className="banner">
      <span>Hello Banner is currently displayed. We are currently in path "/world"</span>
    </div>
  ) 
}

이제 상단 탐색 막대가 있는 기존 웹 애플리케이션의 레이아웃을 상상해 보겠습니다. 탐색 모음에는 앱의 각 섹션에 대한 링크가 포함되어 있으며 본문에는 현재 웹 페이지의 콘텐츠가 표시됩니다. 해당 컨테이너의 스켈레톤 코드는 React에서 다음과 같습니다.


class AppContainer extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div id="div_app_container" className="app-container">
        <div id="div_nav" className="nav-bar">
          <span>Navigation bar</span>
          <Link to="/hello">
            <span>Link to /hello</span>
          </Link>
          <Link to="/world">
            <span>Link to /world</span>
          </Link>
          <Link to="/clearlyinvalidpath">
            <span>Link to a clearly invalid path.</span>
          </Link>
        </div>
        <div id="main_container" className="main-container">
          <span>Main Container</span>
          <Switch>
            <Route exact path="/">
              <div>
                <span>
                  Default container. We are in root path
                </span>
              </div>
            </Route>
            <Route path="/hello" component={HelloBanner} />
            <Route path="/world">
              <WorldBanner />
            </Route>
            <Redirect to="/" />
          </Switch>
        </div>
      </div>
    );
  }
}

ReactDOM.render(
  <BrowserRouter>
    <AppContainer />
  </BrowserRouter>,
  document.getElementById("app")
);

현재 CodePen에서 이 구조의 렌더링을 보고 있다면 다음과 같은 매우 간단한 UI를 볼 수 있습니다.


Example UI탐색 모음에서 <Link>를 클릭하면 해당 경로로 "탐색"됩니다. 실제로 이것이 하는 일은 두 가지입니다.


  • 브라우저의 현재 경로를 표시된 경로로 업데이트합니다.
  • 현재 경로에 따라 다시 렌더링 하도록 모든 <Route> 구성 요소를 업데이트합니다.


이것은 예제 앱을 통해 설명됩니다. / hello 또는 / world에 대한 링크를 클릭하면 해당 구성 요소가 <Switch> 컨테이너 아래에서 교체됩니다.


코드 예제에서 주목할만한 몇 가지 사항 :


  • <Switch> 구성 요소는 <Route> 간의 스왑을 허용하고 주어진 URL 경로로 올바른 구성 요소를 렌더링 합니다. 그러나 <Route> 구성 요소는 <Switch> 안에 래핑 할 필요가 없습니다. 독립형인 동안 <Route>는 URL 경로가 자체 경로 속성과 일치 할 때 간단히 렌더링 됩니다.
  • 끝에 있는 <Redirect> 구성 요소는 기본 경로로 작동합니다. 다른 경로가 현재 URL 경로와 일치하지 않는 경우 사용자를 루트로 다시 리디렉션 합니다.
  • 프로그래밍 방식으로 리디렉션

위에서 설명한 워크 플로는 최종 사용자의 관점에서 직관적입니다. 그러나 애플리케이션의 내부 로직에서 앱 이벤트 이후 수행되는 리디렉션을 요구하는 경우가 있습니다. 이러한 경우 React Router는 히스토리 객체를 활용하여 프로그래밍 방식의 리디렉션을 허용합니다.


기존 설정의 경우 withRouter 상위 구성 요소 사용자를 통해 구성 요소의 소품을 통해 히스토리 개체에 액세스 할 수 있습니다.


import * as React from "react";
import { RouteComponentProps, withRouter } from "react-router-dom";

export interface SampleComponentProps extends RouteComponentProps {
  // props go here
}
export interface SampleComponentStateState {
  // states go here
}

class SampleComponent extends React.Component<SampleComponentProps, SampleComponentStateState> {
  constructor(props: any) {
    super(props);
  }

  performRedirect = () => {
    const { history } = this.props;

    history.push("/desired-pathname")
  }

  render() {
    return <div/>
  }
}

export default withRouter<SampleComponentProps>(SampleComponent);

위의 예에서 히스토리 객체를 추출하는 데 필요한 모든 구성 요소와 리디렉션을 수행하는 history.push () 호출을 볼 수 있습니다.


보다 업데이트 된 접근 방식을 위해 React Router는 React Hooks 집약적 인 워크 플로우로 프로그래밍 할 때 더 자연스럽게 혼합되어야 하는 후크 useHistory를 도입했습니다.


리디렉션시 상태 전달 


특정 리디렉션은 본질적으로 고유하며 새 구성 요소에 전달하려는 이전 사용자 활동에 대한 특정 정보를 포함합니다. 이 경우 정보는 기록 상태를 통해 새 구성 요소로 전달 될 수 있으며, 그러면 다음 상태를 기반으로 사용자 지정 동작을 수행합니다.


<Link> 구성 요소 리디렉션을 사용하는 경우 경로 이름에 대한 문자열 대신 새 경로와 상태가 포함 된 개체로 to prop을 채웁니다.


<Link
  to={{
    pathname: "/desired-pathname",
    state: {
      stateName: "state to be passed."
    }
  }}
>
  Link text here.
</Link>

동일한 객체를 history.push() 호출에 대한 인수로 사용하여 유사한 결과를 얻을 수 있습니다.


history.push({
  pathname: "/desired-pathname",
  state: {
    stateName: "state to be passed."
  }
})

상태가 리디렉션에 포함되면 수신 측에서 history.location.state 객체에서 상태를 추출 할 수 있습니다.


import * as React from "react";
import { RouteComponentProps, withRouter } from "react-router-dom";

export interface ReceivingComponentProps extends RouteComponentProps {
  // props go here
}
export interface ReceivingComponentStateState {
  // states go here
}

class ReceivingComponent extends React.Component<ReceivingComponentProps, ReceivingComponentStateState> {
  constructor(props: any) {
    super(props);
  }

  componentDidMount() {
    const { history } = this.props;
    if (history.location.state && history.location.state.stateName) {
      // stateName can be accessed here if it is passed in from a previous redirect action.
      console.log(history.location.state.stateName);
    }
  }

  render() {
    return <div/>
  }
}

export default withRouter<ReceivingComponentProps>(ReceivingComponent);

상태 액세스는 위의 예에서 componentDidMount에 있습니다.


Parting Words 


이 시점에서 React Router를 사용하여 탐색을 시작하는 데 도움이 되는 모든 주요 항목을 다루었기를 바랍니다. 이 글이 React의 탐색에 대한 이해와 다음 React 애플리케이션 구축에 도움이 되었기를 바랍니다.