클라이언트 라우팅 (react-router 사용) 및 서버 측 라우팅


108

나는 생각하고 클라이언트와 서버 사이의 라우팅과 혼동됩니다. 요청을 웹 브라우저로 다시 보내기 전에 ReactJS를 서버 측 렌더링에 사용하고 react-router를 클라이언트 측 라우팅으로 사용하여 SPA로 새로 고치지 않고 페이지 사이를 전환한다고 가정합니다.

떠오르는 것은 :

  • 경로는 어떻게 해석됩니까? 예를 들어 홈페이지 ( /home)에서 게시물 페이지 ( /posts) 로의 요청
  • 라우팅은 서버 측 또는 클라이언트에서 어디로 이동합니까?
  • 어떻게 처리되는지 어떻게 압니까?

1
브라우저에서 History API를 읽는 것이 좋습니다.
WiredPrairie

답변:


137

이 답변은 React Router 버전 0.13.x를 다룹니다. 다가오는 버전 1.0 은 구현 세부 사항이 크게 다를 것으로 보입니다.

섬기는 사람

이것은 server.jsreact-router를 사용한 최소한의 것 입니다.

var express = require('express')
var React = require('react')
var Router = require('react-router')

var routes = require('./routes')

var app = express()

// ...express config...

app.use(function(req, res, next) {
  var router = Router.create({location: req.url, routes: routes})
  router.run(function(Handler, state) {
    var html = React.renderToString(<Handler/>)
    return res.render('react_page', {html: html})
  })
})

어디 routes모듈은 경로의 목록을 보냅니다

var React = require('react')
var {DefaultRoute, NotFoundRoute, Route} = require('react-router')

module.exports = [
  <Route path="/" handler={require('./components/App')}>
    {/* ... */}
  </Route>
]

서버에 요청이있을 때마다 Router수신 URL을 고정 위치로 사용하여 구성된 일회용 인스턴스 를 생성합니다.이 인스턴스는 경로 트리에 대해 확인되어 적절한 일치 경로를 설정하고 최상위 수준으로 다시 호출됩니다. 렌더링 할 경로 처리기와 각 수준에서 일치하는 자식 경로에 대한 레코드. 이것은 <RouteHandler>일치 된 하위 경로를 렌더링하기 위해 경로 처리 구성 요소 내 에서 구성 요소 를 사용할 때 참조되는 내용 입니다.

사용자가 JavaScript를 끄거나로드 속도가 느리면 클릭하는 모든 링크가 서버에 다시 연결되며 위와 같이 다시 해결됩니다.

고객

이것은 client.jsreact-router (동일한 경로 모듈 재사용)를 사용 하는 최소한의 것 입니다.

var React = require('react')
var Router = require('react-router')

var routes = require('./routes')

Router.run(routes, Router.HistoryLocation, function(Handler, state) {
  React.render(<Handler/>, document.body)
})

를 호출 Router.run()하면 백그라운드에서 라우터 인스턴스가 생성됩니다.이 인스턴스는 앱을 탐색 할 때마다 재사용됩니다. URL은 클라이언트에서 동적 일 수 있습니다. 고정 URL.

이 경우 에는 뒤로 / 앞으로 버튼을 눌렀을 때 올바른 일이 발생하는지 확인하기 위해 APIHistoryLocation사용 History하는를 사용하고 있습니다. 또한 HashLocationURL hash을 변경하여 기록 항목을 만들고 window.onhashchange이벤트를 수신하여 탐색을 트리거하는 것도 있습니다.

react-router의 <Link>구성 요소 를 사용할 때 to경로의 이름 인 prop paramsquery경로에 필요한 데이터를 제공합니다. <a>이 구성 요소에 의해 렌더링은이 onClick궁극적으로 호출 핸들러 router.transitionTo()이처럼 보이는 링크를 준 소품 라우터 인스턴스를 :

  /**
   * Transitions to the URL specified in the arguments by pushing
   * a new URL onto the history stack.
   */
  transitionTo: function (to, params, query) {
    var path = this.makePath(to, params, query);

    if (pendingTransition) {
      // Replace so pending location does not stay in history.
      location.replace(path);
    } else {
      location.push(path);
    }
  },

일반 링크의 경우 이는 궁극적으로 location.push()사용중인 위치 유형을 호출 합니다.이 기능은 내역 설정의 세부 정보를 처리하므로 뒤로 및 앞으로 버튼으로 탐색이 작동 router.handleLocationChange()할 것입니다. 새 URL 경로.

그런 다음 라우터 router.dispatch()는 구성된 경로 중 URL과 일치하는 경로를 확인하는 세부 정보를 처리하는 새 URL로 자체 메서드를 호출 한 다음 일치하는 경로에 대해 존재하는 모든 전환 후크 를 호출합니다 . 라우트 핸들러에서 이러한 전환 후크를 구현하여 경로가 멀어 지거나 이동하려고 할 때 작업을 수행 할 수 있으며, 원하는대로 전환을 중단 할 수 있습니다.

전환이 중단되지 않은 경우 마지막 단계는 Router.run()URL의 모든 세부 정보와 일치하는 경로가있는 상태 개체와 최상위 수준 핸들러 구성 요소 를 사용하여 제공 한 콜백을 호출하는 것 입니다. 최상위 수준 처리기 구성 요소는 실제로 Router일치 된 최상위 경로 처리기를 렌더링하는 인스턴스 자체입니다.

위의 프로세스는 클라이언트에서 새 URL로 이동할 때마다 다시 실행됩니다.

예제 프로젝트


3
따라서 클라이언트 라우팅이있는 경우 자바 스크립트 (반응 라우터 코드)에 의해 처리된다고 말할 수 있습니다. 브라우저 주소 표시 줄에서 Enter 키를 누르거나 페이지를 새로 고치거나 JS를 비활성화 할 때마다 서버 측에서 라우팅을 처리합니다. 반면에 자바 스크립트가 현재 페이지에서 준비되면 라우팅은 클라이언트 측에서 처리됩니다. 내가 올바르게 이해 했습니까?
heartmon

9
라우트 모듈의 내용 var routes = require('./routes')은 라우트 목록입니까? Express 라우터를 사용했지만 여기에있는이 예제는 React Router로 서버 측 렌더링을 설정하는 유일한 예제 인 것 같습니다. 따라서 전체 코드 예제라면 좋을 것입니다
svnm

2
경로 목록이어야합니다. 이에 대한 메모와 예제 프로젝트에 대한 링크를 추가하겠습니다.
Jonny Buchanan

2
그렇다면 react-router가 서버 측 라우팅을 처리한다면 누가 데이터베이스와 통신할까요? 서버 측 라우팅은 어떻게됩니까? 네이티브 모바일 앱에 REST API를 제공하고 싶다고 상상해보십시오. 누가 처리합니까?
Morteza Shahriari Nia

1
최신 react-router버전 으로 인해 답변이 오래되었습니다 . 업데이트 해주세요.
oleh.meleshko 2011 년

26

1.0에서 React-Router 는 peerDependency로 history 모듈 에 의존합니다 . 이 모듈은 브라우저에서 라우팅을 다룹니다. 기본적으로 React-Router는 HTML5 History API ( pushState, replaceState)를 사용하지만 해시 기반 라우팅을 사용하도록 구성 할 수 있습니다 (아래 참조).

경로 처리는 이제이면에서 수행되며 ReactRouter는 경로가 변경 될 때 새로운 props를 Route 핸들러로 보냅니다. 라우터에는 onUpdate경로가 변경 될 때마다 새로운 prop 콜백이 있으며 <title>, 예를 들어 페이지 뷰 추적 또는 .

클라이언트 (HTML5 라우팅)

import {Router} from 'react-router'
import routes from './routes'

var el = document.getElementById('root')

function track(){
  // ...
}

// routes can be children
render(<Router onUpdate={track}>{routes}</Router>, el)

클라이언트 (해시 기반 라우팅)

import {Router} from 'react-router'
import {createHashHistory} from 'history'
import routes from './routes'

var el = document.getElementById('root')

var history = createHashHistory()

// or routes can be a prop
render(<Router routes={routes} history={history}></Router>, el)

섬기는 사람

서버에서 사용할 수 있습니다 ReactRouter.match. 이것은 서버 렌더링 가이드 에서 가져온 것입니다.

import { renderToString } from 'react-dom/server'
import { match, RoutingContext } from 'react-router'
import routes from './routes'

app.get('*', function(req, res) {
  // Note that req.url here should be the full URL path from
  // the original request, including the query string.
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.status(500).send(error.message)
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
      res.status(200).send(renderToString(<RoutingContext {...renderProps} />))
    } else {
      res.status(404).send('Not found')
    }
  })
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.