Я только что заменил react-router
с v3 на v4.
Но я не уверен, как программно перемещаться в функции-члене a Component
. т.е. в handleClick()
функции, к которой я хочу перейти /path/some/where
после обработки некоторых данных. Я использовал это для:
import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')
Но я не могу найти такие интерфейсы в v4.
Как я могу ориентироваться с помощью v4?
reactjs
ecmascript-6
react-router-v4
Колин Виткамп
источник
источник
Component
? Например, внутри редукционных действий.Ответы:
Если вы ориентируетесь на среду браузера, вам нужно использовать
react-router-dom
пакет, а неreact-router
. Они следуют тому же подходу, что и React, чтобы разделить ядро (react
) и код, специфичный для платформы, (react-dom
,react-native
) с тонким отличием в том, что вам не нужно устанавливать два отдельных пакета, поэтому пакеты среды содержат все тебе нужно. Вы можете добавить его в свой проект как:yarn add react-router-dom
или
npm i react-router-dom
Первое, что вам нужно сделать, это предоставить
<BrowserRouter>
самый верхний родительский компонент в вашем приложении.<BrowserRouter>
использует HTML5history
API и управляет им за вас, поэтому вам не нужно беспокоиться о том, чтобы создать его экземпляр самостоятельно и передать его<BrowserRouter>
компоненту в качестве опоры (как это требовалось в предыдущих версиях).В V4 для программной навигации вам необходим доступ к
history
объекту, доступному через Reactcontext
, при условии, что у вас есть компонент<BrowserRouter>
провайдера , который является самым верхним родителем в вашем приложении. Библиотека раскрывает через контекстrouter
объект, который сам содержитhistory
свойство.history
Интерфейс предлагает несколько методов навигации, такие какpush
,replace
иgoBack
, среди прочих. Вы можете проверить весь список свойств и методов здесь .Важное замечание для пользователей Redux / Mobx
Если вы используете redux или mobx в качестве библиотеки управления состоянием в своем приложении, вы можете столкнуться с проблемами с компонентами, которые должны учитывать местоположение, но не будут повторно отображаться после запуска обновления URL-адреса.Это происходит потому, что
react-router
переходитlocation
к компонентам с использованием контекстной модели.2 подхода к решению этой проблемы:
<Route />
. Текущийlocation
объект - это один из реквизитов,<Route>
передаваемых компоненту, который он отображает.withRouter
более высокого порядка, который на самом деле имеет тот же эффект и внедряет,location
что и пропПомимо этого, существует четыре способа программной навигации, упорядоченные по рекомендации:
1.- Использование
Это продвигает декларативный стиль. До версии v4<Route>
компонента<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
. Пример для иллюстрации:2.- Использование
withRouter
HoCЭтот компонент более высокого порядка будет вводить те же реквизиты, что и
Route
. Тем не менее, это ограничивает то, что вы можете иметь только 1 HoC на файл.3.- Использование
РендерингRedirect
компонента<Redirect>
переместится на новое место. Но имейте в виду, что по умолчанию текущее местоположение заменяется новым, как перенаправления на стороне сервера (HTTP 3xx). Новое местоположение обеспечиваетсяto
prop, который может быть строкой (URL-адрес для перенаправления) илиlocation
объектом. Если вы хотите добавить новую запись в историю , передайте такжеpush
опору и установите ее вtrue
4.- Доступ
Немного обескуражен, потому что контекст все еще является экспериментальным API, и он может сломаться / измениться в будущих версиях Reactrouter
вручную через контекстСамо собой разумеется, есть и другие компоненты Router, предназначенные для не браузерных экосистем, например,
<NativeRouter>
которые реплицируют стек памяти в памяти и предназначены для платформы React Native, доступной черезreact-router-native
пакет.Для любой дальнейшей ссылки, не стесняйтесь взглянуть на официальные документы . Также есть видео, сделанное одним из соавторов библиотеки, которое представляет довольно интересное введение в Reaction-router v4, выделяя некоторые из основных изменений.
источник
withRouter
изreact-router-dom
withRouter
изreact-router-dom
. History.push действительно изменяет URL, но, похоже, не загружает,<Route>
пока я не<Router>
внутри компонента React, который украшен@observer
, который вызывает эту проблему .@withRouter
Обходной путь должен иметь каждый такой компонент React.withRouter
просто HOC, который используетRoute
под капотом. Это означает, что он использует только 3 реквизита, историю, совпадение и местоположение . В приведенном выше примере кажется, чтоpush
это опора,withRouter
которая добавитButtonToNavigate
, но это не так.props.history.push
будет использоваться вместо этого. Надеюсь, что это помогает другим, которые были немного смущены.browserHistory.push('/path/some/where')
просто кажется намного проще. Авторы пытаются препятствовать императивному программированию, но иногда оно просто работает лучше!Самый простой способ сделать это:
this.props.history.push("/new/url")
Примечание:
history
prop
родительский компонент компоненту, для которого вы хотите вызвать действие, если оно недоступно.источник
this.props.history
доступных в вашем компоненте, то вы можете,import {withRouter} from 'react-router-dom'
а затемexport default withRouter(MyComponent)
(илиconst MyComponent = withRouter(...)
), и он вставитhistory
элемент в реквизиты вашего компонента.history.push
и просто запустить обновление, как когда мы нажимаем<Link>
У меня была похожая проблема при переходе на React-Router v4, поэтому я попытаюсь объяснить свое решение ниже.
Пожалуйста, не рассматривайте этот ответ как верный способ решения проблемы, я думаю, есть хороший шанс, что что-то лучшее возникнет, когда React Router v4 станет более зрелым и выйдет из бета-версии (возможно, он уже существует, и я его просто не обнаружил) ,
Для контекста у меня была эта проблема, потому что я иногда использую,
Redux-Saga
чтобы программно изменить объект истории (скажем, когда пользователь успешно аутентифицируется).В документации по React Router посмотрите на
<Router>
компонент, и вы увидите, что у вас есть возможность передавать свой собственный объект истории через опору. Это суть решения - мы поставляем объект истории , чтобыReact-Router
из глобального модуля.шаги:
yarn add history
илиnpm install history --save
создать файл с именем
history.js
вApp.js
папке вашего уровня (это было моим предпочтением)Добавьте этот объект истории в ваш компонент Router следующим образом
Настройте URL как и прежде, импортируя свой глобальный объект истории:
Теперь все должно синхронизироваться, и у вас также есть доступ к способу установки объекта истории программно, а не через компонент / контейнер.
источник
Route
компонентом.TL; DR:
Простой и декларативный ответ заключается в том, что вам нужно использовать
<Redirect to={URL} push={boolean} />
в сочетании сsetState()
Полный пример здесь . Узнайте больше здесь .
PS. В примере используются инициализаторы свойств ES7 + для инициализации состояния. Посмотри здесь , если тебе интересно.
источник
history.push()
методов.Используйте
useHistory
хук, если вы используете функциональные компонентыВы можете использовать
useHistory
крюк, чтобы получитьhistory
экземпляр.useHistory
Крюк дает вам доступ к экземпляру истории , которые вы можете использовать для навигации.Использовать
history
свойство внутри компонентов страницыReact Router добавляет некоторые свойства, в том числе
history
к компонентам страницы.Оберните дочерние компоненты,
withRouter
чтобы добавить свойства маршрутизатораwithRouter
Оболочка вводит свойства маршрутизатора в компоненты. Например, вы можете использовать эту оболочку, чтобы внедрить маршрутизатор в компонент кнопки выхода из пользовательского меню.источник
Вы также можете просто использовать реквизит для доступа к объекту истории:
this.props.history.push('new_url')
источник
this.props.history
доступных в вашем компоненте, то вы можете,import {withRouter} from 'react-router-dom'
а затемexport default withRouter(MyComponent)
(илиconst MyComponent = withRouter(...)
), и он вставитhistory
элемент в реквизиты вашего компонента.Шаг 1: сверху можно импортировать только одну вещь:
Шаг 2: В вашем маршруте передайте историю:
Шаг 3: история будет принята как часть реквизита в следующем Компоненте, так что вы можете просто:
Это было легко и действительно мощно.
источник
Это работает:
источник
Мой ответ похож на ответ Алекса . Я не уверен, почему React-Router сделал это настолько излишне сложным. Почему я должен обернуть свой компонент с помощью HoC, чтобы получить доступ к тому, что по сути является глобальным?
В любом случае, если вы посмотрите, как они реализованы
<BrowserRouter>
, это всего лишь крошечная оболочка истории .Мы можем немного извлечь эту историю, чтобы импортировать ее из любого места. Однако хитрость заключается в том, что если вы выполняете рендеринг на стороне сервера и пытаетесь
import
использовать модуль истории, он не будет работать, поскольку он использует API-интерфейсы только для браузера. Но это нормально, потому что мы обычно перенаправляем только в ответ на щелчок или какое-либо другое клиентское событие. Таким образом, это нормально, чтобы подделать это:С помощью веб-пакета мы можем определить некоторые переменные, чтобы мы знали, в какой среде мы находимся:
И теперь вы можете
Откуда угодно. Он просто вернет пустой модуль на сервер.
Если вы не хотите использовать эти магические переменные, вам просто нужно
require
в глобальном объекте, где он необходим (внутри вашего обработчика событий).import
не будет работать, потому что он работает только на верхнем уровне.источник
Я думаю, что @rgommezz охватывает большинство случаев, за исключением одного, который, я думаю, очень важен.
Это позволяет мне написать простой сервис с действиями / вызовами, которые я могу вызвать для навигации по любому компоненту, который я хочу, не делая много HoC для моих компонентов ...
Непонятно, почему никто не предоставил это решение раньше. Я надеюсь, что это поможет, и если вы обнаружите какие-либо проблемы с этим, пожалуйста, дайте мне знать.
источник
Я уже несколько дней тестирую v4 и .. пока что мне это нравится! Это просто имеет смысл через некоторое время.
У меня также был тот же вопрос, и я обнаружил, что обработка его такова, что следующее сработало лучше (и, возможно, даже так, как задумано) Он использует состояние, троичный оператор и
<Redirect>
.В конструкторе ()
В рендере ()
В обработчике кликов ()
Надеюсь, поможет. Дай мне знать.
источник
Некоторое время я боролся с этим - чем-то таким простым, но таким сложным, потому что ReactJS - это совершенно другой способ написания веб-приложений, он очень чужд для нас, пожилых людей!
Я создал отдельный компонент, чтобы абстрагироваться от беспорядка:
Затем добавьте его в ваш
render()
метод:источник
Поскольку нет другого способа справиться с этим ужасным дизайном, я написал общий компонент, который использует подход
withRouter
HOC . В приведенном ниже примере оборачиваетсяbutton
элемент, но вы можете изменить его на любой элемент, который можно щелкнуть:Использование:
источник
Если вы не нашли this.props.history в вашем компоненте, попробуйте это
источник
Поскольку иногда я предпочитаю переключать маршруты по Приложению, а не по кнопкам, это минимальный рабочий пример, который работает для меня:
источник
Для тех из вас, кто требует перенаправления перед полной инициализацией маршрутизатора, используя
React Router
или,React Router Dom
Вы можете предоставить перенаправление, просто получив доступ к объекту истории и выдвинув новое состояние в него в своей конструкцииapp.js
. Учтите следующее:Здесь мы хотим изменить выходные Маршруты, зависящие от субдомена, взаимодействуя с объектом истории до того, как компонент отобразит, мы можем эффективно перенаправить, оставляя наши маршруты в такте.
источник