Программная навигация с использованием реагирующего маршрутизатора
С react-router
Я могу использовать Link
элемент для создания ссылок, которые изначально обрабатываются реагирующим маршрутизатором.
Я вижу внутренне это вызывает this.context.transitionTo(...)
,
Я хочу сделать навигацию, но не по ссылке, например, из выпадающего списка. Как я могу сделать это в коде? Что такое this.context
?
Я видел Navigation
mixin, но я могу сделать это без mixins?
51 ответ
React Router v4
В версии 4 React Router существует три подхода к программной маршрутизации внутри компонентов.
- Использовать
withRouter
Компонент высшего порядка. - Используйте композицию и визуализируйте
<Route>
- Использовать
context
,
React Router - это в основном оболочка history
библиотека. history
обрабатывает взаимодействие с браузером window.history
для вас с его браузером и хэш-историями. Он также предоставляет историю памяти, которая полезна для сред, в которых нет глобальной истории. Это особенно полезно при разработке мобильных приложений (react-native
) и модульное тестирование с Node.
history
Экземпляр имеет два метода навигации: push
а также replace
, Если вы думаете о history
как массив посещенных мест, push
добавит новое местоположение в массив и replace
заменит текущее местоположение в массиве новым. Как правило, вы хотите использовать push
метод при навигации.
В более ранних версиях React Router вам приходилось создавать свои собственные history
экземпляр, но в v4 <BrowserRouter>
, <HashRouter>
, а также <MemoryRouter>
компоненты создадут для вас экземпляры браузера, хэша и памяти. React Router делает свойства и методы history
экземпляр, связанный с вашим маршрутизатором, доступен через контекст, под router
объект.
1. Используйте withRouter
компонент высшего порядка
withRouter
компонент более высокого порядка будет вводить history
объект как опора компонента. Это позволяет вам получить доступ к push
а также replace
методы без необходимости иметь дело с context
,
import { withRouter } from 'react-router-dom'
// this also works with react-router-native
const Button = withRouter(({ history }) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
))
2. Используйте композицию и визуализируйте <Route>
<Route>
Компонент не только для сопоставления мест. Вы можете отобразить маршрут без маршрута, и он всегда будет соответствовать текущему местоположению. <Route>
компонент проходит тот же реквизит, что и withRouter
, так что вы сможете получить доступ к history
методы через history
двигательный
import { Route } from 'react-router-dom'
const Button = () => (
<Route render={({ history}) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
)} />
)
3. Используйте контекст *
* Но вы, вероятно, не должны
Последний вариант - тот, который вы должны использовать, только если вам удобно работать с контекстной моделью React. Несмотря на то, что контекст является опцией, следует подчеркнуть, что контекст является нестабильным API, и в React есть раздел " Почему не использовать контекст" в их документации. Так что используйте на свой страх и риск!
const Button = (props, context) => (
<button
type='button'
onClick={() => {
// context.history.push === history.push
context.history.push('/new-location')
}}
>
Click Me!
</button>
)
// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
history: React.PropTypes.shape({
push: React.PropTypes.func.isRequired
})
}
1 и 2 - самый простой вариант реализации, поэтому для большинства случаев использования они являются вашими лучшими ставками.
React-Router 4.0.0+ Ответ
В 4.0 и выше используйте историю как опору вашего компонента.
class Example extends React.Component {
// use `this.props.history.push('/some/path')` here
};
React-Router 3.0.0+ Ответ
В версии 3.0 и выше используйте маршрутизатор в качестве опоры для вашего компонента.
class Example extends React.Component {
// use `this.props.router.push('/some/path')` here
};
React-Router 2.4.0+ Ответ
В версии 2.4 и выше используйте компонент более высокого порядка, чтобы получить маршрутизатор в качестве опоры для вашего компонента.
import { withRouter } from 'react-router';
class Example extends React.Component {
// use `this.props.router.push('/some/path')` here
};
// Export the decorated class
var DecoratedExample = withRouter(Example);
// PropTypes
Example.propTypes = {
router: React.PropTypes.shape({
push: React.PropTypes.func.isRequired
}).isRequired
};
React-Router 2.0.0+ Ответ
Эта версия обратно совместима с 1.x, поэтому нет необходимости в Руководстве по обновлению. Просто пройтись по примерам должно быть достаточно хорошо.
Тем не менее, если вы хотите переключиться на новый шаблон, внутри маршрутизатора есть модуль browserHistory, к которому вы можете получить доступ с помощью
import { browserHistory } from 'react-router'
Теперь у вас есть доступ к истории браузера, поэтому вы можете выполнять такие операции, как push, replace и т. Д.
browserHistory.push('/some/path')
Дальнейшее чтение: истории и навигация
React-Router 1.xx Ответ
Я не буду вдаваться в детали обновления. Вы можете прочитать об этом в Руководстве по обновлению.
Основное изменение в этом вопросе - это переход от миксина навигации к истории. Теперь он использует историю браузера API для изменения маршрута, поэтому мы будем использовать pushState()
впредь.
Вот пример использования Mixin:
var Example = React.createClass({
mixins: [ History ],
navigateToHelpPage () {
this.history.pushState(null, `/help`);
}
})
Обратите внимание, что это History
происходит от проекта рэкет / история. Не от самого React-Router.
Если вы не хотите использовать Mixin по какой-либо причине (возможно, из-за класса ES6), то вы можете получить доступ к истории, полученной от маршрутизатора. this.props.history
, Он будет доступен только для компонентов, предоставляемых вашим маршрутизатором. Итак, если вы хотите использовать его в любых дочерних компонентах, его нужно передать как атрибут через props
,
Вы можете прочитать больше о новой версии в их документации 1.0.x.
Вот справочная страница, посвященная навигации за пределами вашего компонента
Рекомендуется захватить ссылку history = createHistory()
и звонит replaceState
на что.
React-Router 0.13.x Ответ
Я попал в ту же проблему и смог найти решение только с помощью навигационного миксина, который поставляется с реагирующим маршрутизатором.
Вот как я это сделал
import React from 'react';
import {Navigation} from 'react-router';
let Authentication = React.createClass({
mixins: [Navigation],
handleClick(e) {
e.preventDefault();
this.transitionTo('/');
},
render(){
return (<div onClick={this.handleClick}>Click me!</div>);
}
});
Я смог позвонить transitionTo()
без необходимости доступа .context
Или вы можете попробовать модную ES6 class
import React from 'react';
export default class Authentication extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
this.context.router.transitionTo('/');
}
render(){
return (<div onClick={this.handleClick}>Click me!</div>);
}
}
Authentication.contextTypes = {
router: React.PropTypes.func.isRequired
};
Реагировать-маршрутизатор-Redux
Примечание: если вы используете Redux, есть еще один проект, называемый React-Router-Redux, который дает вам редукционные привязки для ReactRouter, используя несколько такой же подход, как React-Redux
React-Router-Redux имеет несколько доступных методов, которые позволяют легко перемещаться изнутри создателей действий. Они могут быть особенно полезны для людей, которые имеют существующую архитектуру в React Native, и они хотят использовать те же шаблоны в React Web с минимальными дополнительными затратами.
Изучите следующие методы:
push(location)
replace(location)
go(number)
goBack()
goForward()
Вот пример использования с Redux-Thunk:
./actioncreators.js
import { goBack } from 'react-router-redux'
export const onBackPress = () => (dispatch) => dispatch(goBack())
./viewcomponent.js
<button
disabled={submitting}
className="cancel_button"
onClick={(e) => {
e.preventDefault()
this.props.onBackPress()
}}
>
CANCEL
</button>
React-Router v2
Для самой последней версии (v2.0.0-rc5
), рекомендуемый метод навигации - прямое нажатие на историю синглтона. Это можно увидеть в действии в документе " Навигация за пределами компонентов".
Соответствующая выдержка:
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
Если вы используете более новый API реагирующего маршрутизатора, вам необходимо использовать history
от this.props
когда внутри компонентов так:
this.props.history.push('/some/path');
Это также предлагает pushState
но это устарело для зарегистрированных предупреждений.
При использовании react-router-redux
предлагает push
Функция, которую вы можете отправить следующим образом:
import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));
Однако это может использоваться только для изменения URL, а не для перехода на страницу.
React-Router 4.x Ответ:
С моей стороны, мне нравится иметь единственный объект истории, который я могу нести даже за пределами компонентов. Мне нравится иметь один файл history.js, который я импортирую по требованию, и просто манипулировать им.
Вы просто должны изменить BrowserRouter
Маршрутизатор, и укажите реквизиты истории. Это ничего не меняет для вас, за исключением того, что у вас есть свой собственный объект истории, которым вы можете манипулировать, как хотите.
Вам нужно установить историю, библиотека, используемая react-router
,
Пример использования, обозначение ES6:
history.js
import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory()
BasicComponent.js
import React, { Component } from 'react';
import history from './history';
class BasicComponent extends Component {
goToIndex(e){
e.preventDefault();
history.push('/');
}
render(){
return <a href="#" onClick={this.goToIndex}>Previous</a>;
}
}
РЕДАКТИРОВАТЬ 16 апреля 2018 года:
Если вам нужно перейти от компонента, который фактически отображается из Route
компонент, вы также можете получить доступ к истории из реквизита, например:
BasicComponent.js
import React, { Component } from 'react';
class BasicComponent extends Component {
navigate(e){
e.preventDefault();
this.props.history.push('/url');
}
render(){
return <a href="#" onClick={this.navigate}>Previous</a>;
}
}
Вот как вы делаете это с react-router v2.0.0
с ES6. react-router
отошел от миксинов.
import React from 'react';
export default class MyComponent extends React.Component {
navigateToPage = () => {
this.context.router.push('/my-route')
};
render() {
return (
<button onClick={this.navigateToPage}>Go!</button>
);
}
}
MyComponent.contextTypes = {
router: React.PropTypes.object.isRequired
}
Для этого, кто не контролирует серверную часть и из-за этого использует hash router v2:
Поместите свою историю в отдельный файл (например, app_history.js ES6):
import { useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });
export default appHistory;
И используйте это везде!
Ваша точка входа для реагирующего маршрутизатора (app.js ES6):
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Redirect } from 'react-router'
import appHistory from './app_history'
...
const render((
<Router history={appHistory}>
...
</Router>
), document.querySelector('[data-role="app"]'));
Ваша навигация внутри любого компонента (ES6):
import appHistory from '../app_history'
...
ajaxLogin('/login', (err, data) => {
if (err) {
console.error(err); // login failed
} else {
// logged in
appHistory.replace('/dashboard'); // or .push() if you don't need .replace()
}
})
React Router V4
ТЛ: д-р;
if (navigate) {
return <Redirect to="/" push={true} />
}
Простой и декларативный ответ заключается в том, что вам нужно использовать <Redirect to={URL} push={boolean} />
в комбинации с setState()
push: boolean - при значении true перенаправление будет помещать новую запись в историю вместо замены текущей.
import { Redirect } from 'react-router'
class FooBar extends React.Component {
state = {
navigate: false
}
render() {
const { navigate } = this.state
// here is the important part
if (navigate) {
return <Redirect to="/" push={true} />
}
// ^^^^^^^^^^^^^^^^^^^^^^^
return (
<div>
<button onClick={() => this.setState({ navigate: true })}>
Home
</button>
</div>
)
}
}
Полный пример здесь. Узнайте больше здесь.
PS. В примере используются инициализаторы свойств ES7+ для инициализации состояния. Посмотри здесь, если тебе интересно.
Предупреждение: этот ответ охватывает только версии ReactRouter до 1.0
Я обновлю этот ответ вариантами использования 1.0.0-rc1 после!
Вы можете сделать это и без миксинов.
let Authentication = React.createClass({
contextTypes: {
router: React.PropTypes.func
},
handleClick(e) {
e.preventDefault();
this.context.router.transitionTo('/');
},
render(){
return (<div onClick={this.handleClick}>Click me!</div>);
}
});
Гоча с контекстами в том, что он недоступен, если вы не определили contextTypes
на уроке.
Что касается контекста, то это объект, подобный реквизиту, который передается от родителя к потомку, но он передается неявно, без необходимости каждый раз переопределять реквизиты. См. https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html
Я попробовал по крайней мере 10 способов сделать это, прежде чем что-то заработало!
@ Филип Скиннер withRouter
Ответ был немного ошеломляющим для меня, и я не был уверен, что хочу создать новые имена классов "ExportedWithRouter".
Вот самый простой и понятный способ сделать это, около React-Router 3.0.0 и ES6:
React-Router 3.xx с ES6:
import { withRouter } from 'react-router';
class Example extends React.Component {
// use `this.props.router.push('/some/path')` here
};
// Export the decorated class
export default withRouter(Example);
или, если это не ваш класс по умолчанию, экспортируйте как:
withRouter(Example);
export { Example };
Обратите внимание, что в 3.xx <Link>
сам компонент использует router.push
, так что вы можете передать все, что вы передадите <Link to=
тег, как:
this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'
Чтобы выполнить навигацию программно, вам нужно добавить новую историю в props.history в вашем component
так что-то вроде этого может сделать работу за вас:
//using ES6
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick(e) {
e.preventDefault()
/* Look at here, you can add it here */
this.props.history.push('/redirected');
}
render() {
return (
<div>
<button onClick={this.handleClick}>
Redirect!!!
</button>
</div>
)
}
}
export default App;
Для компонентов ES6 + React у меня сработало следующее решение.
Я последовал за Фелиппом Скиннером, но добавил комплексное решение, чтобы помочь таким начинающим, как я.
Ниже приведены версии, которые я использовал:
"response-router": "^ 2.7.0"
"реагировать": "^15.3.1"
Ниже приведен мой компонент реакции, где я использовал программную навигацию с использованием реагирующего маршрутизатора:
import React from 'react';
class loginComp extends React.Component {
constructor( context) {
super(context);
this.state = {
uname: '',
pwd: ''
};
}
redirectToMainPage(){
this.context.router.replace('/home');
}
render(){
return <div>
// skipping html code
<button onClick={this.redirectToMainPage.bind(this)}>Redirect</button>
</div>;
}
};
loginComp.contextTypes = {
router: React.PropTypes.object.isRequired
}
module.exports = loginComp;
Ниже приведена конфигурация для моего маршрутизатора:
import { Router, Route, IndexRedirect, browserHistory } from 'react-router'
render(<Router history={browserHistory}>
<Route path='/' component={ParentComp}>
<IndexRedirect to = "/login"/>
<Route path='/login' component={LoginComp}/>
<Route path='/home' component={HomeComp}/>
<Route path='/repair' component={RepairJobComp} />
<Route path='/service' component={ServiceJobComp} />
</Route>
</Router>, document.getElementById('root'));
В реакции роутера v4. Я следую этому двухстороннему маршруту программно.
1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")
Номер два
Заменяет текущую запись в стеке истории
Чтобы получить историю в реквизитах, вам, возможно, придется обернуть свой компонент с
withRouter https://reacttraining.com/react-router/core/api/withRouter
Возможно, это не лучший подход, но... С помощью response-router v4 следующий Typescript может дать представление для некоторых.
В представленном компоненте ниже, например LoginPage
, router
объект доступен и просто позвоните router.transitionTo('/homepage')
для навигации.
Навигационный код был взят из https://react-router.now.sh/Match.
"react-router": "^4.0.0-2",
"react": "^15.3.1",
import Router from 'react-router/BrowserRouter';
import { History } from 'react-history/BrowserHistory';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
interface MatchWithPropsInterface {
component: typeof React.Component,
router: Router,
history: History,
exactly?: any,
pattern: string
}
class MatchWithProps extends React.Component<MatchWithPropsInterface,any> {
render() {
return(
<Match {...this.props} render={(matchProps) => (
React.createElement(this.props.component, this.props)
)}
/>
)
}
}
ReactDOM.render(
<Router>
{({ router }) => (
<div>
<MatchWithProps exactly pattern="/" component={LoginPage} router={router} history={history} />
<MatchWithProps pattern="/login" component={LoginPage} router={router} history={history} />
<MatchWithProps pattern="/homepage" component={HomePage} router={router} history={history} />
<Miss component={NotFoundView} />
</div>
)}
</Router>,
document.getElementById('app')
);
С React-Router v4 на горизонте, теперь есть новый способ сделать это.
import { MemoryRouter, BrowserRouter } from 'react-router';
const navigator = global && global.navigator && global.navigator.userAgent;
const hasWindow = typeof window !== 'undefined';
const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1;
const Router = isBrowser ? BrowserRouter : MemoryRouter;
<Router location="/page-to-go-to"/>
response-lego - это пример приложения, которое показывает, как использовать / обновлять реактив-маршрутизатор, и включает примеры функциональных тестов, которые перемещаются по приложению.
Использовать withRouter
с компонентом на основе классов, попробуйте что-то вроде этого ниже. Не забудьте изменить инструкцию экспорта для использования withRouter
:
import { withRouter } from 'react-router-dom'
class YourClass extends React.Component {
yourFunction = () => {
doSomeAsyncAction(() =>
this.props.history.push('/other_location')
)
}
render() {
return (
<div>
<Form onSubmit={ this.yourFunction } />
</div>
)
}
}
export default withRouter(YourClass);
В React-Router v4 и ES6
Ты можешь использовать withRouter
а также this.props.history.push
,
import {withRouter} from 'react-router-dom';
class Home extends Component {
componentDidMount() {
this.props.history.push('/redirect-to');
}
}
export default withRouter(Home);
Основываясь на предыдущем ответе
от Хосе Антонио Постиго и Бена Уилера
новинка? должен быть написан в Typescript
и использование декораторов
ИЛИ статическое свойство / поле
import * as React from "react";
import Component = React.Component;
import { withRouter } from "react-router";
export interface INavigatorProps {
router?: ReactRouter.History.History;
}
/**
* Note: goes great with mobx
* @inject("something") @withRouter @observer
*/
@withRouter
export class Navigator extends Component<INavigatorProps, {}>{
navigate: (to: string) => void;
constructor(props: INavigatorProps) {
super(props);
let self = this;
this.navigate = (to) => self.props.router.push(to);
}
render() {
return (
<ul>
<li onClick={() => this.navigate("/home")}>
Home
</li>
<li onClick={() => this.navigate("/about")}>
About
</li>
</ul>
)
}
}
/**
* Non decorated
*/
export class Navigator2 extends Component<INavigatorProps, {}> {
static contextTypes = {
router: React.PropTypes.object.isRequired,
};
navigate: (to: string) => void;
constructor(props: INavigatorProps, context: any) {
super(props, context);
let s = this;
this.navigate = (to) =>
s.context.router.push(to);
}
render() {
return (
<ul>
<li onClick={() => this.navigate("/home")}>
Home
</li>
<li onClick={() => this.navigate("/about")}>
About
</li>
</ul>
)
}
}
с любым установленным сегодня npm. "response-router": "^3.0.0" и
"@types/ реакции-маршрутизатор": "^2.0.41"
Для тех, кто уже использует React Router v6, это можно сделать с помощью
useNavigate
крючок, предоставленный
react-router
.
Навигация с помощью этого хука довольно проста:
import { generatePath, useNavigate } from 'react-router';
navigate(-1); // navigates back
navigate('/my/path'); // navigates to a specific path
navigate(generatePath('my/path/:id', { id: 1 })); // navigates to a dynamic path, generatePath is very useful for url replacements
Для последней версии react-router-dom v6
useHistory()
заменяется на
useNavigate()
.
Вам нужно использовать:
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('/your-page-link');
Обновление: React Router v6 с хуками
import {useNavigate} from 'react-router-dom';
let navigate = useNavigate();
navigate('home');
И чтобы перемещаться по истории браузера,
navigate(-1); ---> Go back
navigate(1); ---> Go forward
navigate(-2); ---> Move two steps backward.
С текущей версией React (15.3), this.props.history.push('/location');
работал для меня, но он показал следующее предупреждение:
browser.js: 49 Предупреждение: [реагирует на маршрутизатор]
props.history
а такжеcontext.history
устарели. Пожалуйста, используйтеcontext.router
,
и я решил это с помощью context.router
как это:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.backPressed = this.backPressed.bind(this);
}
backPressed() {
this.context.router.push('/back-location');
}
...
}
MyComponent.contextTypes = {
router: React.PropTypes.object.isRequired
};
export default MyComponent;
Если вы используете хеш или историю браузера, то вы можете сделать
hashHistory.push('/login');
browserHistory.push('/login');
React-Router V4
если вы используете версию 4, то вы можете использовать мою библиотеку (плагин Shameless), где вы просто отправляете действие, и все просто работает!
dispatch(navigateTo("/aboutUs"));
Те, кто сталкивается с проблемами в реализации этого на реакции-маршрутизатор v4. Вот рабочее решение для навигации по приложению реагировать на редукционные действия.
history.js
import createHistory from 'history/createBrowserHistory'
export default createHistory()
App.js / Route.jsx
import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
<Route path="/test" component={Test}/>
</Router>
файл other_file.js/redux
import history from './history'
history.push('/test') // this should change the url and re-render Test component
Все благодаря этому комментарию: https://github.com/ReactTraining/react-router/issues/3498
Вы также можете использовать useHistory
перехватить компонент без состояния. Пример из документации.
import { useHistory } from "react-router"
function HomeButton() {
const history = useHistory()
return (
<button type="button" onClick={() => history.push("/home")}>
Go home
</button>
)
}
Примечание: хуки были добавлены в
react-router@5.1.0
и требоватьreact@>=16.8
Программная навигация в компонентах на основе классов.
import { Redirect } from "react-router-dom";
class MyComponent extends React.Component{
state= {rpath: null}
const goTo= (path)=> this.setState({rpath: path});
render(){
if(this.state.rpath){
return <Redirect to={this.state.rpath}/>
}
.....
.....
}
}
Надеюсь, поможет.
Итак, в моем ответе есть 3 разных способа программного перенаправления на маршрут. Некоторые решения уже были представлены, а следующие ориентированы только на функциональные компоненты с дополнительным демонстрационным приложением.
Используя следующие версии:
реагировать: 16.13.1
реагировать-дом: 16.13.1
реагировать-маршрутизатор: 5.2.0
реагировать-маршрутизатор-дом: 5.2.0
машинописный текст: 3.7.2
Конфигурация:
Итак, в первую очередь решение использует HashRouter
, настроенный следующим образом:
<HashRouter>
// ... buttons for redirect
<Switch>
<Route exact path="/(|home)" children={Home} />
<Route exact path="/usehistory" children={UseHistoryResult} />
<Route exact path="/withrouter" children={WithRouterResult} />
<Route exact path="/redirectpush" children={RedirectPushResult} />
<Route children={Home} />
</Switch>
</HashRouter>
Из документации о<HashRouter>
:
А
<Router>
который использует хеш-часть URL-адреса (т.е.window.location.hash
), чтобы ваш пользовательский интерфейс синхронизировался с URL-адресом.
Решения:
- С помощью
<Redirect>
толкать с помощьюuseState
:
Использование в функциональном компоненте (RedirectPushAction
компонент из моего репозитория) мы можем использовать useState
для обработки перенаправления. Сложная часть заключается в том, что после перенаправления нам нужно установитьredirect
состояние обратно к false
. ИспользуяsetTimeOut
с 0
задержка мы ждем пока React зафиксирует Redirect
в DOM, а затем верните кнопку, чтобы использовать в следующий раз.
Пожалуйста, найдите мой пример ниже:
const [redirect, setRedirect] = useState(false);
const handleRedirect = useCallback(() => {
let render = null;
if (redirect) {
render = <Redirect to="/redirectpush" push={true} />
// in order wait until commiting to the DOM
// and get back the button for clicking next time
setTimeout(() => setRedirect(false), 0);
}
return render;
}, [redirect]);
return <>
{handleRedirect()}
<button onClick={() => setRedirect(true)}>
Redirect push
</button>
</>
От <Redirect>
документация:
Оказание
<Redirect>
перейдет в новое место. Новое местоположение переопределит текущее местоположение в стеке истории, как это делают перенаправления на стороне сервера (HTTP 3xx).
- С помощью
useHistory
крючок:
В моем решении есть компонент под названием UseHistoryAction
что представляет собой следующее:
let history = useHistory();
return <button onClick={() => { history.push('/usehistory') }}>
useHistory redirect
</button>
В
useHistory
hook дает нам доступ к объекту истории, который помогает нам программно перемещаться или изменять маршруты.
- С помощью
withRouter
, получитьhistory
отprops
:
Создан один компонент под названием WithRouterAction
, отображается, как показано ниже:
const WithRouterAction = (props:any) => {
const { history } = props;
return <button onClick={() => { history.push('/withrouter') }}>
withRouter redirect
</button>
}
export default withRouter(WithRouterAction);
Чтение из withRouter
документация:
Вы можете получить доступ к
history
свойства объекта и ближайшего<Route>
совпадение черезwithRouter
компонент высшего порядка.withRouter
пройдет обновленныйmatch
,location
, а такжеhistory
props для обернутого компонента всякий раз, когда он отрисовывается.
Демо:
Для лучшего представления я создал репозиторий GitHub с этими примерами, вы можете найти его ниже:
https://github.com/norbitrial/react-router-programmatically-redirect-examples
Надеюсь, это поможет!
Если случится с парой RR4 с редуксом через Reaction -router-redux, используйте создателей действий маршрутизации из react-router-redux
вариант также.
import { push, replace, ... } from 'react-router-redux'
class WrappedComponent extends React.Component {
handleRedirect(url, replaceState = true) {
replaceState
? this.props.dispatch(replace(url))
: this.props.dispatch(push(url))
}
render() { ... }
}
export default connect(null)(WrappedComponent)
Если для управления асинхронным потоком используется redux thunk/saga, лучше импортируйте создателей вышеуказанных действий в действиях redux и подключайте для реагирования компоненты, используя mapDispatchToProps.
Вместо этого используйте hookrouter, современную альтернативу response-router
https://www.npmjs.com/package/hookrouter
import { useRoutes, usePath, A} from "hookrouter";
чтобы ответить на вопрос OP о связывании через поле выбора, вы можете сделать это:
navigate('/about');
Возможно, не лучшее решение, но оно выполняет свою работу:
import { Link } from 'react-router-dom';
// create functional component Post
export default Post = () => (
<div className="component post">
<button className="button delete-post" onClick={() => {
// ... delete post
// then redirect, without page reload, by triggering a hidden Link
document.querySelector('.trigger.go-home').click();
}}>Delete Post</button>
<Link to="/" className="trigger go-home hidden"></Link>
</div>
);
По сути, логика, связанная с одним действием (в данном случае удаление сообщения), в итоге вызовет триггер для перенаправления. Это не идеально, потому что вы добавите триггер DOM-узла к вашей разметке, чтобы вы могли удобно вызывать его при необходимости. Кроме того, вы будете напрямую взаимодействовать с DOM, что в компоненте React может быть нежелательно.
Тем не менее, этот тип перенаправления не требуется так часто. Таким образом, одна или две дополнительные скрытые ссылки в разметке вашего компонента не повредят так сильно, особенно если вы дадите им значимые имена.