React-router: как вручную вызывать ссылку?
Я новичок в ReactJS и React-Router. У меня есть компонент, который получает через реквизит <Link/>
объект из реагирующего маршрутизатора. Всякий раз, когда пользователь нажимает кнопку "next" внутри этого компонента, я хочу вызвать объект <Link/>
вручную.
В настоящий момент я использую refs для доступа к экземпляру поддержки и ручному нажатию на тег 'a', который генерирует <Link/>
.
Вопрос: Есть ли способ вручную вызвать ссылку (например, this.props.next.go
)?
Это текущий код, который у меня есть:
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />
//in Document.js
...
var Document = React.createClass({
_onClickNext: function() {
var next = this.refs.next.getDOMNode();
next.querySelectorAll('a').item(0).click(); //this sounds like hack to me
},
render: function() {
return (
...
<div ref="next">{this.props.next} <img src="rightArrow.png" onClick={this._onClickNext}/></div>
...
);
}
});
...
Это код, который я хотел бы иметь:
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />
//in Document.js
...
var Document = React.createClass({
render: function() {
return (
...
<div onClick={this.props.next.go}>{this.props.next.label} <img src="rightArrow.png" /> </div>
...
);
}
});
...
Ответы
Ответ 1
React Router v4 - компонент Redirect (обновлено 2017/04/15)
Рекомендуемый способ v4 - позволить вашему методу визуализации перехватить перенаправление. Используйте состояние или реквизит, чтобы определить, должен ли отображаться компонент перенаправления (который затем вызывает перенаправление).
import { Redirect } from 'react-router';
// ... your class implementation
handleOnClick = () => {
// some action...
// then redirect
this.setState({redirect: true});
}
render() {
if (this.state.redirect) {
return <Redirect push to="/sample" />;
}
return <button onClick={this.handleOnClick} type="button">Button</button>;
}
Ссылка: https://reacttraining.com/react-router/web/api/Redirect
React Router v4 - Контекст справочного маршрутизатора
Вы также можете воспользоваться контекстом Router
, который отображается в компоненте React.
static contextTypes = {
router: PropTypes.shape({
history: PropTypes.shape({
push: PropTypes.func.isRequired,
replace: PropTypes.func.isRequired
}).isRequired,
staticContext: PropTypes.object
}).isRequired
};
handleOnClick = () => {
this.context.router.push('/sample');
}
Вот как работает <Redirect />
под капотом.
Ссылка: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60
React Router v4 - Объект истории с внешней мутацией
Если вам все равно нужно сделать что-то похожее на реализацию v2, вы можете создать копию BrowserRouter
, а затем выставить history
в качестве экспортируемой константы. Ниже приведен базовый пример, но вы можете скомпоновать его, если нужно, с помощью настраиваемых реквизитов. Есть отмеченные оговорки с жизненными циклами, но он всегда должен повторять Router, как и в v2. Это может быть полезно для перенаправления после запроса API из функции действия.
// browser router file...
import createHistory from 'history/createBrowserHistory';
import { Router } from 'react-router';
export const history = createHistory();
export default class BrowserRouter extends Component {
render() {
return <Router history={history} children={this.props.children} />
}
}
// your main file...
import BrowserRouter from './relative/path/to/BrowserRouter';
import { render } from 'react-dom';
render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
// some file... where you don't have React instance references
import { history } from './relative/path/to/BrowserRouter';
history.push('/sample');
Последние BrowserRouter
для расширения: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js
React Router v2
Нажмите новое состояние в экземпляр browserHistory
:
import {browserHistory} from 'react-router';
// ...
browserHistory.push('/sample');
Ссылка: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md
Ответ 2
React Router 4 включает в себя withRouter HOC, который дает вам доступ к объекту history
через this.props
:
import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'
class Foo extends Component {
constructor(props) {
super(props)
this.goHome = this.goHome.bind(this)
}
goHome() {
this.props.history.push('/')
}
render() {
<div className="foo">
<button onClick={this.goHome} />
</div>
}
}
export default withRouter(Foo)
Ответ 3
https://github.com/rackt/react-router/blob/bf89168acb30b6dc9b0244360bcbac5081cf6b38/examples/transitions/app.js#L50
или вы даже можете попробовать выполнить onClick this (более жестокое решение):
window.location.assign("/sample");
Ответ 4
Хорошо, я думаю, что смог найти подходящее решение для этого.
Теперь вместо отправки <Link/>
как prop в Document, я отправляю <NextLink/>
, который является настраиваемой оболочкой для Link-маршрутизатора Link. Делая это, я могу иметь правую стрелку как часть структуры Link, все еще избегая иметь код маршрутизации внутри объекта Document.
Обновленный код выглядит следующим образом:
//in NextLink.js
var React = require('react');
var Right = require('./Right');
var NextLink = React.createClass({
propTypes: {
link: React.PropTypes.node.isRequired
},
contextTypes: {
transitionTo: React.PropTypes.func.isRequired
},
_onClickRight: function() {
this.context.transitionTo(this.props.link.props.to);
},
render: function() {
return (
<div>
{this.props.link}
<Right onClick={this._onClickRight} />
</div>
);
}
});
module.exports = NextLink;
...
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
var nextLink = <NextLink link={sampleLink} />
<Document next={nextLink} />
//in Document.js
...
var Document = React.createClass({
render: function() {
return (
...
<div>{this.props.next}</div>
...
);
}
});
...
P.S. Если вы используете последнюю версию реактивного маршрутизатора, вам может понадобиться this.context.router.transitionTo
вместо this.context.transitionTo
. Этот код будет отлично работать для версии-ретранслятора версии 0,12.X.
Ответ 5
React Router 4
Вы можете легко вызвать метод push через контекст в v4:
this.context.router.push(this.props.exitPath);
где контекст:
static contextTypes = {
router: React.PropTypes.object,
};
Ответ 6
опять же это JS :) это все еще работает....
var linkToClick = document.getElementById('something');
linkToClick.click();
<Link id="something" to={/somewhaere}> the link </Link>