Note, esta resposta cobre React Router versão 0.13.x - a próxima versão 1.0 parece que terá detalhes de implementação significativamente diferentes
Servidor
Isso é mínimo server.js
com 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})
})
})
Onde o routes
módulo exporta uma lista de Rotas:
var React = require('react')
var {DefaultRoute, NotFoundRoute, Route} = require('react-router')
module.exports = [
<Route path="/" handler={require('./components/App')}>
{/* ... */}
</Route>
]
Cada vez que uma solicitação é feita ao servidor, você cria uma Router
instância de uso único configurada com o URL de entrada como seu local estático, que é resolvido na árvore de rotas para configurar as rotas correspondentes adequadas, chamando de volta com o nível superior o manipulador de rotas a ser renderizado e um registro de quais rotas secundárias correspondem em cada nível. Isso é o que é consultado quando você usa o <RouteHandler>
componente dentro de um componente de manipulação de rota para renderizar uma rota secundária que foi correspondida.
Se o usuário tiver o JavaScript desativado ou se ele estiver demorando para carregar, todos os links em que ele clicar chegarão ao servidor novamente, o que é resolvido como descrito acima.
Cliente
Isso é mínimo client.js
com react-router (reutilizando o mesmo módulo de rotas):
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)
})
Quando você chama Router.run()
, ele cria uma instância de Roteador para você nos bastidores, que é reutilizada toda vez que você navega pelo aplicativo, já que a URL pode ser dinâmica no cliente, ao contrário do servidor onde uma única solicitação tem um URL fixo.
Nesse caso, estamos usando o HistoryLocation
, que usa a History
API para garantir que a coisa certa aconteça quando você clicar no botão voltar / avançar. Há também um HashLocation
que altera o URL hash
para fazer entradas de histórico e ouve o window.onhashchange
evento para acionar a navegação.
Quando você usa de reagir-router <Link>
componente, você dar-lhe um to
suporte que é o nome de uma rota, além de quaisquer params
e query
de dados das necessidades de rota. O <a>
renderizado por este componente tem um onClick
manipulador que, em última análise, chama router.transitionTo()
a instância do roteador com os props que você forneceu ao link, que se parece com isto:
/**
* 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);
}
},
Para um link regular, isso acaba chamando location.push()
qualquer tipo de local que você está usando, que lida com os detalhes de configuração do histórico para que a navegação com os botões voltar e avançar funcione e, em seguida, chama de volta para router.handleLocationChange()
para informar ao roteador que pode prosseguir com a transição para o novo caminho de URL.
O roteador então chama seu próprio router.dispatch()
método com a nova URL, que lida com os detalhes de determinar quais das rotas configuradas correspondem à URL, a seguir chama quaisquer ganchos de transição presentes para as rotas correspondentes. Você pode implementar esses ganchos de transição em qualquer um de seus manipuladores de rota para realizar alguma ação quando uma rota estiver prestes a ser navegada ou afastada, com a capacidade de abortar a transição se as coisas não forem do seu agrado.
Se a transição não foi abortada, a etapa final é chamar o retorno de chamada que você deu Router.run()
com o componente manipulador de nível superior e um objeto de estado com todos os detalhes do URL e as rotas correspondentes. O componente manipulador de nível superior é, na verdade, a Router
própria instância, que lida com a renderização do manipulador de rota superior que foi correspondido.
O processo acima é executado novamente sempre que você navegar para um novo URL no cliente.
Projetos de exemplo