나는 생각하고 클라이언트와 서버 사이의 라우팅과 혼동됩니다. 요청을 웹 브라우저로 다시 보내기 전에 ReactJS를 서버 측 렌더링에 사용하고 react-router를 클라이언트 측 라우팅으로 사용하여 SPA로 새로 고치지 않고 페이지 사이를 전환한다고 가정합니다.
떠오르는 것은 :
- 경로는 어떻게 해석됩니까? 예를 들어 홈페이지 (
/home
)에서 게시물 페이지 (/posts
) 로의 요청 - 라우팅은 서버 측 또는 클라이언트에서 어디로 이동합니까?
- 어떻게 처리되는지 어떻게 압니까?
답변
이 답변은 React Router 버전 0.13.x를 다룹니다. 다가오는 버전 1.0 은 구현 세부 사항이 크게 다를 것으로 보입니다.
섬기는 사람
이것은 server.js
react-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.js
react-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.
이 경우 에는 뒤로 / 앞으로 버튼을 눌렀을 때 올바른 일이 발생하는지 확인하기 위해 API 를 HistoryLocation
사용 History
하는를 사용하고 있습니다. 또한 HashLocation
URL hash
을 변경하여 기록 항목을 만들고 window.onhashchange
이벤트를 수신하여 탐색을 트리거하는 것도 있습니다.
react-router의 <Link>
구성 요소 를 사용할 때 to
경로의 이름 인 prop params
과 query
경로에 필요한 데이터를 제공합니다. <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로 이동할 때마다 다시 실행됩니다.
예제 프로젝트
답변
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')
}
})
})