С помощью react-router
я могу использовать элемент Link
для создания ссылок, которые изначально обрабатываются маршрутизатором react.
Я вижу внутри это называется this.context.transitionTo (...)
.
Я хочу сделать навигацию, но не по ссылке, например, из выпадающего списка. Как я могу сделать это в коде? Что такое this.context
?
Я видел миксин "Навигация", но могу ли я сделать это без миксинов?
React Router v5.1.0 с крючками
В React Router > 5.1.0 появился новый крючок «useHistory», если вы используете React > 16.8.0 и функциональные компоненты.
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
React Router v4
С v4 React Router есть три подхода, которые вы можете использовать для программной маршрутизации внутри компонентов.
withRouter
высшего порядка.< Route >
context
.React Router - это в основном оболочка вокруг библиотеки history
. history
обрабатывает взаимодействие с браузером window.history
для вас с его браузером и историями хешей. Он также предоставляет историю памяти, которая полезна для сред, которые не имеют глобальной истории. Это особенно полезно при разработке мобильных приложений (react-native
) и модульном тестировании с помощью Node.
Экземпляр history
имеет два метода навигации: push
и replace
. Если вы рассматриваете «историю» как массив посещенных местоположений, «push» добавит новое местоположение в массив, а «заменить» заменит текущее местоположение в массиве новым. Обычно вы хотите использовать метод push
при навигации.
В более ранних версиях React Router вам приходилось создавать свой собственный экземпляр history
, но в v4 - < BrowserRouter >
,< HashRouter >
и< MemoryRouter >
компоненты создадут браузер, хэш и экземпляры памяти для вас. React Router делает свойства и методы экземпляра history
, связанного с вашим маршрутизатором, доступными через контекст под объектом router
.
withRouter
высшего порядкаКомпонент withRouter
высшего порядка будет вводить объект history
как опору компонента. Это позволяет получить доступ к методам «push» и «заменить» без необходимости иметь дело с «контекстом».
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>
))
< 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>
)} />
)
Но вы, вероятно, не должны
Последний вариант - тот, который вы должны использовать, только если вам удобно работать с моделью React context. Хотя контекст является вариантом, следует подчеркнуть, что контекст является нестабильным 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 - самый простой выбор для реализации, поэтому для большинства случаев использования они являются вашими лучшими ставками.
& Лт; br / > Кроме того, вы можете получить больше знаний по нижним ссылкам о маршрутизации, параметрах URL и вложенной маршрутизации.
Маршрутизация в React JS < br / >
Параметры URL с помощью React Router < br / >
Вложенные маршруты в React JS < br / >
Надеюсь, это поможет вам!
React-Router 5.1.0+ Ответ (с использованием крючков и React > 16.8)
Вы можете использовать новый крючок useHistory
для функциональных компонентов и программно перемещаться:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
// use history.push('/some/path') here
};
React-Router 4.0.0+ Ответ
В 4.0 и выше используйте историю как опору вашего компонента.
class Example extends React.Component {
// use `this.props.history.push('/some/path')` here
};
ПРИМЕЧАНИЕ: this.props.history не существует в случае, если ваш компонент не был представлен < Route >
. Вы должны использовать < Маршрут пути = "..."component = {YourComponent} / >
иметь этот.props.history в YourComponent
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} из 'react-router'
Теперь у вас есть доступ к истории вашего браузера, поэтому вы можете делать такие вещи, как push, map и т. Д... Подобно:
browserHistory.push ('/ some/path')
Дальнейшее чтение: Истории и Навигация
React-Router 1.x.x Ответ
Я не буду вдаваться в подробности обновления. Об этом вы можете прочитать в Руководстве по обновлению
Основное изменение в вопросе здесь - переход от навигационного миксина к истории. Теперь он использует историю браузера API для изменения маршрута, поэтому мы будем использовать pushState ()
отныне.
Вот пример с использованием Mixin:
var Example = React.createClass({
mixins: [ History ],
navigateToHelpPage () {
this.history.pushState(null, `/help`);
}
})
Обратите внимание, что эта «История» происходит из проекта rackt / 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
};
React-Router-Redux
Примечание: если вы используете Redux, есть еще один проект под названием React-Router-Redux, который дает вам Привязки редукса для ReactRouter, использующие несколько тот же подход, что и React-Redux делает
React-Router-Redux имеет несколько доступных методов, которые позволяют легко перемещаться от создателей внутренних действий. Они могут быть особенно полезны для людей, которые имеют существующую архитектуру в React Native, и они хотят использовать те же шаблоны в React Web с минимальными накладными расходами на шаблон.
Изучите следующие методы:
push (местоположение)
заменить (местоположение)
go (число)
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
) рекомендуемый метод навигации заключается в непосредственном переходе к истории синглтон. Вы можете видеть это в действии в < a href = "https://github.com/rackt/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md"> Навигация вне компонентов doc < / a >.
Соответствующий отрывок:
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
При использовании более нового API-интерфейса react-router вам необходимо использовать 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 v2.0.0
с [ES6] ( http://babeljs.io/blog/2015/06/07/reacton. «Реактивный роутер» отошел от миксинов.
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
}
React-Router 4.x Ответ:
С моей стороны, мне нравится иметь один объект истории, который я могу нести даже за пределами компонентов. Что мне нравится делать, так это иметь один файл history.js, который я импортирую по требованию, и просто манипулировать им.
Вам просто нужно изменить BrowserRouter
на Router и указать опору истории. Это ничего не меняет для вас, кроме того, что у вас есть свой собственный объект истории, которым вы можете манипулировать по своему усмотрению.
Вам необходимо установить history, библиотеку, используемую 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>;
}
}
EDIT 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>;
}
}
Для этого, кто не контролирует сторону сервера и из-за этого использует хэш-маршрутизатор v2:
Поместите свою историю в отдельный файл (например,. app_history.js ES6):
import { useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });
export default appHistory;
И использовать его везде!
Ваша точка входа для react-router (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
tl: dr ;
if (navigate) {
return <Redirect to="/" push={true} />
}
Простой и декларативный ответ заключается в том, что вам нужно использовать < Перенаправить на = {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 способов сделать это, прежде чем что-то сработало правильно!
Ответ @Felipe Skinner withRouter
был для меня немного ошеломляющим, и я не был уверен, что хочу делать новые названия классов "ExportedWithRouter".
Вот самый простой и чистый способ сделать это, около текущих React-Router 3.0.0 и ES6:
React-Router 3.x.x с 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.x.x сам компонент < Link >
используетrouter.push
, поэтому вы можете передать его всем, что вы передадите тег < Link to =
, например:
this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'
Чтобы выполнить навигацию программно, вам нужно нажать новую history на 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;
Может быть не лучший подход, но... Используя react-router v4, следующий Typescript может дать представление для некоторых.
В визуализированном компоненте ниже, например,. LoginPage
, объект router
доступен и просто вызывайте router.transitionTo ('/ homepage')
для навигации.
Код навигации был взят из.
"react-router": "^ 4.0.0-2",
"react": "^ 15.3.1",
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
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')
);
& Лт;!- конец фрагмента - >
Для компонентов ES6 + React для меня работало следующее решение.
Я последовал за Фелиппе Скиннером, но добавил комплексное решение, чтобы помочь начинающим, как я.
Ниже приведены версии, которые я использовал:
«Реактивный роутер»: «^ 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'));
В 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);
Чтобы использовать withRouter
с компонентом на основе классов, попробуйте что-то подобное ниже.
Не забудьте изменить экспортную выписку, чтобы использовать withRouter
:
import {withRouter} из '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);
на основании предыдущего ответа от Jos & # 233; Антонио Постиго и Бен Уилер новинка? должен быть написан на 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, установленным сегодня. "react-router": "^ 3.0.0" и "@ types / react-router": "^ 2.0.41"
В реакте роутер v4. Я следую этим двум путям к программному маршруту.
1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")
Номер два
Заменяет текущую запись в стеке истории
Чтобы получить историю в реквизите, вам, возможно, придется обернуть свой компонент
с 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"/>
react-lego - это пример приложения, который показывает [как использовать / обновить react-router](https://github.com/peter- mouland / react-lego/compare/react-router-4) и включает в себя примеры функциональных тестов, которые перемещаются в приложении.
Если вы используете историю хэша или браузера, вы можете это сделать
hashHistory.push('/login');
browserHistory.push('/login');
С текущей версией React (15.3) this.props.history.push ('/ location');
работал для меня, но он показал следующее предупреждение:
browser.js: 49 Предупреждение: [react-router]
props.history
andcontext.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;
React-Router V4
если вы используете версию 4, вы можете использовать мою библиотеку (бесстыдный плагин), где вы просто отправляете действие, и все просто работает!
dispatch(navigateTo("/aboutUs"));