我刚刚把react-router从v3替换为v4。 但我不确定如何以编程方式在组件的成员函数中导航。 即在handleClick()函数中,我想在处理一些数据后导航到/path/some/where。 我以前是这样做的:
import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')
但是我在v4中找不到这样的界面。 如何使用v4导航?
我刚刚把react-router从v3替换为v4。 但我不确定如何以编程方式在组件的成员函数中导航。 即在handleClick()函数中,我想在处理一些数据后导航到/path/some/where。 我以前是这样做的:
import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')
但是我在v4中找不到这样的界面。 如何使用v4导航?
当前回答
如果使用函数组件,请使用useHistory钩子
你可以使用useHistory钩子获取历史实例。
import { useHistory } from "react-router-dom";
const MyComponent = () => {
const history = useHistory();
return (
<button onClick={() => history.push("/about")}>
Click me
</button>
);
}
useHistory钩子使您可以访问用于导航的历史实例。
在页面组件中使用history属性
React Router向页面组件注入一些属性,包括历史记录。
class HomePage extends React.Component {
render() {
const { history } = this.props;
return (
<div>
<button onClick={() => history.push("/projects")}>
Projects
</button>
</div>
);
}
}
用throuter包装子组件以注入路由器属性
withRouter包装器将路由器属性注入组件。例如,您可以使用此包装器注入路由器注销按钮组件放置在用户菜单。
import { withRouter } from "react-router";
const LogoutButton = withRouter(({ history }) => {
return (
<button onClick={() => history.push("/login")}>
Logout
</button>
);
});
export default LogoutButton;
其他回答
我的答案和Alex的相似。我不知道为什么React-Router把这个做得如此复杂。为什么我必须用一个HoC来包装我的组件,只是为了访问本质上是全局的?
不管怎样,如果你看一下他们是如何实现<BrowserRouter>的,它只是一个历史记录的小包装。
我们可以把这段历史提取出来,这样我们就可以从任何地方导入。然而,诀窍在于,如果您正在进行服务器端呈现,并试图导入历史模块,那么它将无法工作,因为它使用的是纯浏览器api。但这没关系,因为我们通常只在响应单击或其他客户端事件时重定向。因此,假装一下是可以的:
// history.js
if(__SERVER__) {
module.exports = {};
} else {
module.exports = require('history').createBrowserHistory();
}
在webpack的帮助下,我们可以定义一些变量,这样我们就知道我们所处的环境:
plugins: [
new DefinePlugin({
'__SERVER__': 'false',
'__BROWSER__': 'true', // you really only need one of these, but I like to have both
}),
现在你可以
import history from './history';
从任何地方。它只会在服务器上返回一个空模块。
如果你不想使用这些神奇的变量,你只需要在需要它的全局对象中(在你的事件处理程序中)。导入不能工作,因为它只在顶层工作。
因为有时我更喜欢通过应用程序切换路由,然后通过按钮,这是一个最小的工作示例,对我有用:
import { Component } from 'react'
import { BrowserRouter as Router, Link } from 'react-router-dom'
class App extends Component {
constructor(props) {
super(props)
/** @type BrowserRouter */
this.router = undefined
}
async handleSignFormSubmit() {
await magic()
this.router.history.push('/')
}
render() {
return (
<Router ref={ el => this.router = el }>
<Link to="/signin">Sign in</Link>
<Route path="/signin" exact={true} render={() => (
<SignPage onFormSubmit={ this.handleSignFormSubmit } />
)} />
</Router>
)
}
}
如此:
import { withRouter } from 'react-router-dom';
const SomeComponent = withRouter(({ history }) => (
<div onClick={() => history.push('/path/some/where')}>
some clickable element
</div>);
);
export default SomeComponent;
最简单的方法是:
this.props.history.push(“/new/url”)
注意:
如果历史道具不可用,你可以将它从父组件传递到你想调用该动作的组件。
你可以通过这种方式有条件地导航
import { useHistory } from "react-router-dom";
function HomeButton() {
const history = useHistory();
function handleClick() {
history.push("/path/some/where");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}