我迫不及待地跳上了最新的alpha版本react-router
v4。全新<BrowserRouter/>
在保持用戶界面與瀏覽器歷史記錄同步方面非常出色,但如何使用它來以編程方式導航?在React-Router v4中以編程方式導航
回答
路由器將推動一個history
對象到props
散列中的組件。因此,在你的組件,簡單地做:
this.props.history.push('/mypath')
這是一個完整的例子:
在App.js
:
import React from 'react'
import {BrowserRouter as Router, Route} from 'react-router-dom'
import Login from './Login'
export default class App extends React.Component {
render() {
return (
<Router>
<div>
<Route exact path='/login' component={Login} />
</div>
</Router>
)
}
}
在Login.js
:
import React, {PropTypes} from 'react'
export default class Login extends React.Component {
constructor(props) {
super(props)
this.handleLogin = this.handleLogin.bind(this)
}
handleLogin(event) {
event.preventDefault()
// do some login logic here, and if successful:
this.props.history.push(`/mypath`)
}
render() {
return (
<div>
<form onSubmit={this.handleLogin}>
<input type='submit' value='Login' />
</form>
</div>
)
}
}
woow謝謝。這節省了我的一天。完美地與最新版本的反應和反應路由器 –
投擲錯誤'無法讀取未定義的屬性'對象,任何破解? –
@PardeepJain你可以包括堆棧跟蹤的頂部幾行,如果有的話? –
在過去,您可能使用browserHistory
推新路徑。這不適用於react-router
v4。相反,您已經使用了React的context
和router
的transitionTo
方法。
這裏有一個簡單的例子:
import React from 'react';
class NavigateNext extends React.Component {
constructor() {
super();
this.navigateProgramatically = this.navigateProgramatically.bind(this);
}
navigateProgramatically(e) {
e.preventDefault();
this.context.router.transitionTo(e.target.href)
}
render() {
return (
<Link to={"/next-page"}
onClick={this.navigateProgramatically}
>Continue</Link>
);
}
}
NavigateNext.contextTypes = {
router: React.PropTypes.object
};
transitionTo
纔有效router
方法之一。 router
對象還包含blockTransitions(getPromptMessage)
,createHref(to)
和replaceWith(loc)
值得檢查。
這裏的official react-router
tutorial提到以上方法。 如果你想了解更多關於使用react
的context
請查看docs。
我想這樣做,但上下文對象中的路由器變量是未定義的。 「不知何故」它是Link.js中的有效變量。任何想法如何獲得Link.js以外的路由器對象? – singularity
我正在使用redux。如何從動作創建者訪問路由器對象? – Kaidjin
這不適合我。我最終發現,你需要的一切都通過'props'傳遞給你的組件!所有你需要的是'this.props.history.push('/ mypath')'。我在下面的單獨答案中給出了完整的示例:http://stackoverflow.com/a/43250939/1533892 –
我沒有足夠的評論聲望,但是在回答@ singularity的問題時,您必須在組件類'contextTypes
靜態屬性中包含您希望提供的上下文屬性。
如果沒有定義contextTypes,那麼上下文將是一個空對象。
在這種情況下:
class NavigateNext extends React.Component {
// ...
static contextTypes = {
router: PropTypes.object
}
// ...
}
不像propTypes
,contextTypes
實際上會導致反應表現不同,不僅是類型檢查。
謝謝你提出這一點。我在propTypes上設置了'router'而不是contextTypes。 – Marek
謝謝這就是缺少的。現在我可以使用this.context.history.goBack() – tjones0808
react-router v4 beta發佈了,API改變了一點點。如果您使用的是最新版本,則不要使用this.context.router.transitionTo(e.target.href)
做,this.context.router.push(e.target.href)
。
鏈接到新文檔中:https://reacttraining.com/react-router/#context.router
我正在使用react-router-dom版本4.1.2,我得到這個工作的唯一方法是使用'this.context.router.history.push('/' )'。也許這會幫助別人。 – Marek
我發現使用狀態,三元運營商和<Redirect>
效果最好。我認爲這也是最好的方式,因爲它最接近v4的設置方式。
在構造函數()
this.state = {
redirectTo: null
}
this.clickhandler = this.clickhandler.bind(this);
在渲染()
render(){
return (
<div>
{ this.state.redirectTo ?
<Redirect to={{ pathname: this.state.redirectTo }} /> :
(
<div>
..
<button onClick={ this.clickhandler } />
..
</div>
)
}
在clickHandler()
this.setState({ redirectTo: '/path/some/where' });
希望它能幫助。讓我知道。
使用重定向不會導航到新狀態,但會替換歷史記錄中的當前狀態,因此無法導航回去。 –
使用withRouter
:
import React, { PropTypes } from 'react'
import { withRouter } from 'react-router'
// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
}
render() {
const { match, location, history } = this.props
return (
<div>You are now at {location.pathname}</div>
)
}
}
// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation)
使用withRouter
將增加路由器的性能給您組件,那麼你就可以訪問history
和使用push
像你這樣有V3:
import React from 'react';
import { withRouter } from 'react-router-dom';
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
input: '',
};
this._submit = this._submit.bind(this);
}
render() {
return (
<form onSubmit={this._submit}>
<input type="text" onChange={(event) => this.setState({input: event.target.value})}/>
<button type="submit">Submit</button>
</form>
);
}
_submit(event) {
event.preventDefault();
this.props.history.push(`/theUrlYouWantToGoTo`);
}
}
export default withRouter(Form);
工作就像一個魅力,任何人都討厭React路由器就像我一樣,這將工作;) –
爲什麼不使用
如果您需要在某個位置的組件之外進行導航您無法從類似於您在舊版本中使用browserHistory的組件中傳入歷史記錄對象,您可以執行以下操作。
首先創建一個歷史模塊
History.js:
import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory();
然後,當你在聲明路由器確保從反應路由器導入路由器和沒有反應過來路由器-DOM(這是隻是一個包裝反應路由器版本,但會自動創建歷史記錄對象),並通過您剛纔創建
Root.js(或任何你這樣做)的履歷模塊:
import Router from 'react-router/Router'
import history from './history'
...
class Root extends Component{
render() {
return (
<Router history={history}>
...
</Router>
);
}
}
現在您的應用程序將使用您創建的自定義創建的歷史記錄。您現在可以將該歷史模塊導入到任何位置,只需執行history.replace等操作即可,就像您以前使用browserHistory所做的一樣。
SomeModule.js:
import history from './history';
export default()=>{
// redirecting to login page using history without having to pass it in
// from a component
history.replace('/login')
}
當然,這並非是推薦的方式就像在舊版本使用browserHistory是不是因爲像服務器端渲染將無法正常工作的推薦方法,但如果你不關心這往往是正確的解決方案。
一個額外的好處做,這是你可以增加歷史記錄對象的事情說謊解析的查詢字符串PARAMS像這樣的例子:
import createBrowserHistory from 'history/createBrowserHistory'
import queryString from 'query-string';
const history = createBrowserHistory();
history.location.query = queryString.parse(history.location.search);
history.listen(() => {
history.location.query = queryString.parse(history.location.search);
});
export default history;
如果您需要訪問歷史部件之外(例如,在redux actions)react-router發佈了他們原來的解決方案here。
基本上,你必須創建自己的歷史對象:
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
,並傳遞給你的路由器:
import { Router } from 'react-router-dom';
ReactDOM.render((
<Router history={history}> // <<-- the history object
<App/>
</Router>
), document.getElementById('root'))
注:必須使用普通路由器,而不是BrowserRouter或HashRouter在這裏!
如果你現在出口history
,你可以用它在任何地方工作:
import history from './history';
history.push('/home');
- 1. 以編程方式在iOS中導航
- 2. 以編程方式停止導航
- 3. 以編程方式導航w/HashRouter
- 4. 如何使用react-router v4以編程方式從動作創建者導航?
- 5. 以編程方式構建/導航導航控制器
- 6. 如何以編程方式導航導航控制器堆棧?
- 7. 如何以編程方式在GateIn中創建導航
- 8. 如何在ReportViewer中以編程方式進行頁面導航?
- 9. 在Windows Media Center中以編程方式導航
- 10. 如何在Office 2010插件中以編程方式導航?
- 11. 以編程方式在ViewDidLoad()中不更改導航欄高度?
- 12. 如何以編程方式打開引導移動導航欄?
- 13. 以編程方式導航到JSF 2.0中的錯誤頁面
- 14. 以編程方式隱藏導航欄中react-native-router-flux
- 15. 以編程方式在導航欄內嵌入分段控件
- 16. C#Silverlight 3 - 以編程方式在頁面之間導航?
- 17. 以編程方式導航linux shell應用程序
- 18. 如何以編程方式導航(不選擇,但導航)WPF TreeView?
- 19. ReactRouter V4 - 重定向不帶開關
- 20. 如何在導航欄中以編程方式在Objective-C中放置導航項?
- 21. 以編程方式導航到Windows Mobile主屏幕
- 22. 以編程方式禁用默認Android TV導航音效
- 23. 以編程方式獲取導航欄的高度
- 24. 如何以編程方式導航到Web窗體
- 25. iOS以編程方式向下鑽取導航堆棧
- 26. 以編程方式更改導航欄標題
- 27. 如何以編程方式設置導航欄的位置
- 28. 以編程方式推送時導航欄消失
- 29. React路由器,以編程方式導航時傳遞數據?
- 30. 如何以編程方式添加導航控制器?
spik3s:注意,接受的答案沒有工作,但是這一個是:https://stackoverflow.com/a/43250939/1533892 - 可能有助於讀者接受這一個。免責聲明:工作答案是我的:) –
@HarlanTWood謝謝!沒有時間更新我的答案,感謝您的支持。已經將您的答案標記爲正確。 – spik3s
非常好,謝謝:) –