BrowserHistory vs HashHistory¶
До текущего времени мы использовали browserHistory
(смотри src/index.js
).
Можно использовать и hashHistory
. Замените в src/index.js
все вхождения browserHistory
на hashHistory
, откройте снова localhost:3000
, видите в адресе #
? Покликайте по ссылкам.
"Мусор" в адресе используется так сказать, для того чтобы приблизиться к нативному поведению браузера. Что-то вроде уникального ключа. (дословно здесь (EN)).
Спрашивается, зачем нам hashHistory
? Ответ простой - если использовать hashHistory
, придется меньше телодвижений делать для настройки роутинга на сервере. Давайте вернемся к browserHistory
, а так же добавим компонент <NotFound />
.
src/components/NotFound.js
import React, { Component } from 'react' import { Link } from 'react-router' export default class NotFound extends Component { render() { return ( <div className="container"> <div className="row"> <div className="col-md-12"> Страница не найдена. Вернуться на <Link to="/">главную</Link>? </div> </div> </div> ) } }
Добавим <NotFound />
в список роутов:
import 'babel-polyfill' import React from 'react' import { render } from 'react-dom' import App from './containers/App' import Admin from './components/Admin' import Genre from './components/Genre' import Home from './components/Home' import NotFound from './components/NotFound' import { Router, Route, IndexRoute, browserHistory } from 'react-router' render( <Router history={browserHistory}> <Route path="/" component={App}> <IndexRoute component={Home} /> <Route path="admin" component={Admin} /> <Route path="genre" component={Genre} /> </Route> {/* для всех остальных роутов: показывай NotFound */} <Route path="*" component={NotFound} /> </Router>, document.getElementById('root') )
Попробуйте открыть http://localhost:3000/genrepewpewpew
А теперь - http://localhost:3000/genrepewpewpew/anotherpage
Почему? Зайдите на вкладку Network и проверьте, что отдает сервер внутри bundle.js
Корректный bundle.js
для http://localhost:3000/genrepewpewpew
Некорректный bundle.js
для http://localhost:3000/genrepewpewpew/anotherpage
Как думаете, в чем проблема?
Ответ кроется во фразе: "нам придется меньше телодвижений делать для настройки роутинга на сервере". Посмотрите сами
server.js
app.get(/.*/, function root(req, res) { res.sendFile(__dirname + '/index.html') })
Переведем написанное: на все запросы отдавай index.html
. Код index.html
предельно прост:
index.html
<!DOCTYPE html> <html> <head> <title>React Router [RU]Tutorial</title> </head> <body> <div id="root"></div> <script src="dist/bundle.js"></script> </body> </html>
Тем не менее, здесь допущена ошибка! Используется относительный путь для файла bundle.js
, снова посмотрим в консоль хрома:
К счастью, такую ошибку легко исправить, и мы по прежнему можем лицезреть красивый вид адресов, используя browserHistory
.
index.html
<!DOCTYPE html> <html> <head> <title>React Router [RU]Tutorial</title> </head> <body> <div id="root"></div> <!-- добавим / в пути к bundle.js --> <script src="/dist/bundle.js"></script> </body> </html>
Не забудьте перезапустить webpack, так как index.html
не находится под наблюдением для пересборки.
Проверьте куда уходит запрос для bundle.js
сейчас и убедитесь, что путь верен. Убедитесь, что в случае неправильного адреса показывается компонент <NotFound />
.
Альтернативное мнение James K Nelson'a: не нужно использовать pushState (а следовательно browserHistory).
P.S. James предлагает вообще не использовать react-router
, но нам же нужно что-то разбирать в этом туториале ;)
Итого: browserHistory
требует большей поддержки на сервере, но url-адрес выглядит симпатичнее.
Исходный код на данный момент.