使用react-router
我可以使用Link
元素创建由 react 路由器本地处理的链接。
我在内部看到它调用this.context.transitionTo(...)
。
我想进行导航,但不是从链接,例如下拉选择。我怎么能在代码中这样做?什么是this.context
?
我看到了Navigation
mixin,但是我可以不使用 mixin 吗?
反应路由器 v4
使用 React Router 的 v4,您可以采用三种方法在组件内进行编程路由。
withRouter
高阶组件。 <Route>
context
。 React Router 主要是history
库的包装器。 history
通过浏览器和哈希历史history
处理与浏览器window.history
交互。它还提供了一个内存历史记录,对于没有全局历史记录的环境非常有用。这在移动应用程序开发( react-native
)和 Node 的单元测试中特别有用。
history
实例有两种导航方法: push
和replace
。如果您将history
视为已访问位置的数组,则push
将向阵列添加新位置,并且replace
将使用新位置replace
阵列中的当前位置。通常,您需要在导航时使用push
方法。
在早期版本的 React Router 中,您必须创建自己的history
实例,但在第 4 版中, <BrowserRouter>
, <HashRouter>
和<MemoryRouter>
组件将为您创建浏览器,哈希和内存实例。 React Router 通过router
对象下的上下文使与路由器关联的history
实例的属性和方法可用。
withRouter
高阶组件 withRouter
高阶组件将history
对象注入为组件的 prop。这允许您访问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>
))
<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 的上下文模型时才能使用的选项。虽然上下文是一个选项,但应该强调上下文是一个不稳定的 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'
现在您可以访问浏览器历史记录,因此您可以执行推送,替换等操作...
browserHistory.push('/some/path')
React-Router 1.xx答案
我不打算升级细节。您可以在 “ 升级指南” 中阅读相关内容
这里问题的主要变化是从导航 mixin 到 History 的变化。现在它正在使用浏览器 historyAPI 来改变路由,所以从现在开始我们将使用pushState()
。
这是使用 Mixin 的例子:
var Example = React.createClass({
mixins: [ History ],
navigateToHelpPage () {
this.history.pushState(null, `/help`);
}
})
请注意,此History
来自rackt / history项目。不是来自 React-Router 本身。
如果您由于某种原因不想使用 Mixin(可能是因为 ES6 类),那么您可以从this.props.history
访问从路由器获得的历史记录。它只能由路由器呈现的组件访问。所以,如果你想在任何子组件中使用它,它需要通过props
作为属性传递下来。
您可以在1.0.x 文档中阅读有关新版本的更多信息
它建议抓取引用history = createHistory()
并在其上调用replaceState
。
React-Router 0.13.x答案
我遇到了同样的问题,只能通过 react-router 附带的 Navigation mixin 找到解决方案。
这就是我做到的
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,还有另一个名为React-Router-Redux 的项目 ,它为 ReactRouter 提供了 redux 绑定,使用的方法与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');
如果使用较新的 react-router API,则需要在组件内部使用this.props
中的history
,这样:
this.props.history.push('/some/path');
它还提供pushState
但每个已记录的警告都会弃用。
如果使用react-router-redux
,它提供了一个push
函数,你可以像这样调度:
import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));
但是,这可能仅用于更改 URL,而不是实际导航到页面。