Если вы ориентируетесь на среду браузера, вам нужно использовать react-router-dom
пакет, а не react-router
. Они следуют тому же подходу, что и React, чтобы разделить ядро ( react
) и код, специфичный для платформы, ( react-dom
, react-native
) с тонким отличием в том, что вам не нужно устанавливать два отдельных пакета, поэтому пакеты среды содержат все тебе нужно. Вы можете добавить его в свой проект как:
yarn add react-router-dom
или
npm i react-router-dom
Первое, что вам нужно сделать, это предоставить <BrowserRouter>
самый верхний родительский компонент в вашем приложении. <BrowserRouter>
использует HTML5 history
API и управляет им за вас, поэтому вам не нужно беспокоиться о том, чтобы создать его экземпляр самостоятельно и передать его <BrowserRouter>
компоненту в качестве опоры (как это требовалось в предыдущих версиях).
В V4 для программной навигации вам необходим доступ к history
объекту, доступному через React context
, при условии, что у вас есть компонент <BrowserRouter>
провайдера , который является самым верхним родителем в вашем приложении. Библиотека раскрывает через контекст router
объект, который сам содержит history
свойство. history
Интерфейс предлагает несколько методов навигации, такие как push
, replace
и goBack
, среди прочих. Вы можете проверить весь список свойств и методов здесь .
Важное замечание для пользователей Redux / Mobx
Если вы используете redux или mobx в качестве библиотеки управления состоянием в своем приложении, вы можете столкнуться с проблемами с компонентами, которые должны учитывать местоположение, но не будут повторно отображаться после запуска обновления URL-адреса.
Это происходит потому, что react-router
переходит location
к компонентам с использованием контекстной модели.
И connect, и наблюдатель создают компоненты, чьи методы shouldComponentUpdate проводят поверхностное сравнение своих текущих и следующих компонентов. Эти компоненты будут перерисовываться только тогда, когда хотя бы одна опора была изменена. Это означает, что для того, чтобы они обновлялись при изменении местоположения, им необходимо предоставить реквизит, который изменяется при изменении местоположения.
2 подхода к решению этой проблемы:
- Оберните ваш подключенный компонент в без пути
<Route />
. Текущий location
объект - это один из реквизитов, <Route>
передаваемых компоненту, который он отображает.
- Оберните подключенный компонент компонентом
withRouter
более высокого порядка, который на самом деле имеет тот же эффект и внедряет, location
что и проп
Помимо этого, существует четыре способа программной навигации, упорядоченные по рекомендации:
1.- Использование <Route>
компонента
Это продвигает декларативный стиль. До версии v4
<Route />
компоненты размещались в верхней части иерархии компонентов, поэтому необходимо заранее продумать структуру маршрутов. Тем не менее, теперь вы можете иметь
<Route>
компоненты в
любом месте вашего дерева, что позволяет вам лучше контролировать условный рендеринг в зависимости от URL.
Route
внедряет
match
,
location
и
history
как подпирает в ваш компонент. Методы навигации (такие как
push
,
replace
,
goBack
...) доступны как свойства
history
объекта.
Есть 3 способа рендеринга чего-либо с помощью Route
, или component
, render
или children
реквизита, но не используйте более одного в одном Route
. Выбор зависит от варианта использования, но в основном первые два параметра будут отображать ваш компонент, только если он path
соответствует расположению URL, тогда как с children
компонентом будет отображаться, соответствует ли путь местоположению или нет (полезно для настройки интерфейса на основе URL соответствия).
Если вы хотите , чтобы настроить выход компонентного рендеринга , вам нужно обернуть компонент в функции и использовать render
опцию для того, чтобы перейти к компоненте любые другие реквизита вы желаете, кроме match
, location
и history
. Пример для иллюстрации:
import { BrowserRouter as Router } from 'react-router-dom'
const ButtonToNavigate = ({ title, history }) => (
<button
type="button"
onClick={() => history.push('/my-new-location')}
>
{title}
</button>
);
const SomeComponent = () => (
<Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} />
)
const App = () => (
<Router>
<SomeComponent /> // Notice how in v4 we can have any other component interleaved
<AnotherComponent />
</Router>
);
2.- Использование withRouter
HoC
Этот компонент более высокого порядка будет вводить те же реквизиты, что и Route
. Тем не менее, это ограничивает то, что вы можете иметь только 1 HoC на файл.
import { withRouter } from 'react-router-dom'
const ButtonToNavigate = ({ history }) => (
<button
type="button"
onClick={() => history.push('/my-new-location')}
>
Navigate
</button>
);
ButtonToNavigate.propTypes = {
history: React.PropTypes.shape({
push: React.PropTypes.func.isRequired,
}),
};
export default withRouter(ButtonToNavigate);
3.- Использование Redirect
компонента
Рендеринг
<Redirect>
переместится на новое место. Но имейте в виду, что
по умолчанию текущее местоположение заменяется новым, как перенаправления на стороне сервера (HTTP 3xx). Новое местоположение обеспечивается
to
prop, который может быть строкой (URL-адрес для перенаправления) или
location
объектом. Если вы хотите
добавить новую запись в историю , передайте также
push
опору и установите ее в
true
<Redirect to="/your-new-location" push />
4.- Доступ router
вручную через контекст
Немного обескуражен, потому что
контекст все еще является экспериментальным API, и он может сломаться / измениться в будущих версиях React
const ButtonToNavigate = (props, context) => (
<button
type="button"
onClick={() => context.router.history.push('/my-new-location')}
>
Navigate to a new location
</button>
);
ButtonToNavigate.contextTypes = {
router: React.PropTypes.shape({
history: React.PropTypes.object.isRequired,
}),
};
Само собой разумеется, есть и другие компоненты Router, предназначенные для не браузерных экосистем, например, <NativeRouter>
которые реплицируют стек памяти в памяти и предназначены для платформы React Native, доступной через react-router-native
пакет.
Для любой дальнейшей ссылки, не стесняйтесь взглянуть на официальные документы . Также есть видео, сделанное одним из соавторов библиотеки, которое представляет довольно интересное введение в Reaction-router v4, выделяя некоторые из основных изменений.