# BrowserHistory vs HashHistory

*ОБНОВЛЕНИЕ 2018: в учебнике хорошая теория, но ему уже два года. Проверяйте версии пакетов. За выходом нового учебника можно следить в* [*telegram канале*](http://bit.ly/2FI9nhs) *или* [*twitter*](http://bit.ly/2FU6zRL)

*На* [*канале*](http://bit.ly/2FI9nhs) *так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы,* [*присоединяйтесь*](http://bit.ly/2FI9nhs)*!*

## BrowserHistory vs HashHistory

*(глава для расширения кругозора)*

До текущего времени мы использовали *browserHistory* (смотри *src/index.js*).

Можно использовать и *hashHistory*. Замените в *src/index.js* все вхождения browserHistory на hashHistory, откройте снова `localhost:3000`, видите в адресе #? Покликайте по ссылкам.

![hash history](/files/-LvLn_b-WDiuZmAeUUTI)

"Мусор" в адресе используется так сказать, для того чтобы приблизиться к нативному поведению браузера. Что-то вроде уникального ключа. (дословно [здесь](https://github.com/reactjs/react-router-tutorial/tree/master/lessons/02-rendering-a-route) (EN)).

Спрашивается, зачем нам *hashHistory* ? Ответ простой - если использовать *hashHistory*, придется меньше телодвижений делать для настройки роутинга на сервере. Давайте вернемся к *browserHistory*, а так же добавим компонент `<NotFound />`.

*src/components/NotFound.js*

```javascript
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 />` в список роутов:

```javascript
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>

![correct not found](/files/-LvLn_b2ecVzD0_mGrC9)

А теперь - <http://localhost:3000/genrepewpewpew/anotherpage>

![incorrect nof found](/files/-LvLn_b4gCdqQ_-n4L5m)

Почему? Зайдите на вкладку Network и проверьте, что отдает сервер внутри *bundle.js*

Корректный *bundle.js* для <http://localhost:3000/genrepewpewpew>

![correct bundle IMG](/files/-LvLn_b6qXdLGstN5zYU)

Некорректный *bundle.js* для <http://localhost:3000/genrepewpewpew/anotherpage>

![incorrect bundle IMG](/files/-LvLn_b8gZ23l512vzcE)

Как думаете, в чем проблема?

Ответ кроется во фразе: "нам придется меньше телодвижений делать для настройки роутинга на сервере". Посмотрите сами

*server.js*

```javascript
app.get(/.*/, function root(req, res) {
  res.sendFile(__dirname + '/index.html');
});
```

Переведем написанное: на все запросы отдавай **index.html**. Код *index.html* предельно прост:

*index.html*

```markup
<!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*, снова посмотрим в консоль хрома:

![incorrect bundle path screen](/files/-LvLn_bAlbxJbjQR1b2O)

К счастью, такую ошибку легко исправить, и мы по прежнему можем лицезреть красивый вид адресов, используя *browserHistory*.

*index.html*

```markup
<!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 />`

![correct bundle path screen](/files/-LvLn_bCogKUctDI76KF)

[Альтернативное мнение](http://jamesknelson.com/push-state-vs-hash-based-routing-with-react-js/) James K Nelson'a: не нужно использовать pushState (а следовательно browserHistory).

*P.S. James* [*предлагает*](http://jamesknelson.com/routing-with-raw-react/) *вообще не использовать react-router, но нам же нужно что-то разбирать в этом туториале ;)*

**Итого**: *browserHistory* требует большей поддержки на сервере, но url-адрес выглядит симпатичнее.

[Исходный код](https://github.com/maxfarseer/react-router-ru-tutorial/tree/browserHistory_vs_hashHistory) на данный момент.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://max-frontend.gitbook.io/react-router-course-ru/podklyuchaem_react-router/browserhistory_vs_hashhistory.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
