在当前版本的React Router (v3)中,我可以接受服务器响应并使用browserHistory。点击进入相应的响应页面。但是,这在v4中是不可用的,我不确定处理它的适当方法是什么。
在这个例子中,使用Redux, components/app-product-form.js在用户提交表单时调用this.props. addproduct (props)。当服务器返回成功时,用户将被带到Cart页面。
// actions/index.js
export function addProduct(props) {
return dispatch =>
axios.post(`${ROOT_URL}/cart`, props, config)
.then(response => {
dispatch({ type: types.AUTH_USER });
localStorage.setItem('token', response.data.token);
browserHistory.push('/cart'); // no longer in React Router V4
});
}
如何从React Router v4的函数重定向到购物车页面?
使用回调。这对我很管用!
export function addProduct(props, callback) {
return dispatch =>
axios.post(`${ROOT_URL}/cart`, props, config)
.then(response => {
dispatch({ type: types.AUTH_USER });
localStorage.setItem('token', response.data.token);
callback();
});
}
在组件中,你只需要添加回调
this.props.addProduct(props, () => this.props.history.push('/cart'))
这是我的hack(这是我的根级文件,其中混合了一些redux -尽管我没有使用react-router-redux):
const store = configureStore()
const customHistory = createBrowserHistory({
basename: config.urlBasename || ''
})
ReactDOM.render(
<Provider store={store}>
<Router history={customHistory}>
<Route component={({history}) => {
window.appHistory = history
return (
<App />
)
}}/>
</Router>
</Provider>,
document.getElementById('root')
)
然后,我可以在任何我想要的地方使用window.appHistory.push()(例如,在我的redux商店函数/ thacks /sagas等),我希望我可以只使用window.customHistory.push(),但出于某种原因,react-router似乎从未更新,即使url发生了变化。但是这样我就有了react-router使用的EXACT实例。我不喜欢把东西放在全球范围内,这是我做过的为数不多的事情之一。但在我看来,这比我见过的任何其他选择都要好。
这个棘手的问题,花了我很多时间,但最终,我是这样解决的:
用withRouter包装容器,并将历史记录传递给mapDispatchToProps函数中的动作。实际操作中使用history.push('/url')进行导航。
行动:
export function saveData(history, data) {
fetch.post('/save', data)
.then((response) => {
...
history.push('/url');
})
};
容器:
import { withRouter } from 'react-router-dom';
...
const mapDispatchToProps = (dispatch, ownProps) => {
return {
save: (data) => dispatch(saveData(ownProps.history, data))}
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));
这对React Router v4.x有效。
React Router 4中最简单的方法是使用
this.props.history.push('/new/url');
但是要使用此方法,您现有的组件应该能够访问历史对象。我们可以通过
If your component is linked to Route directly, then your component already has access to history object.
eg:
<Route path="/profile" component={ViewProfile}/>
Here ViewProfile has access to history.
If not connected to Route directly.
eg:
<Route path="/users" render={() => <ViewUsers/>}
Then we have to use withRouter, a heigher order fuction to warp the existing component.
Inside ViewUsers component
import { withRouter } from 'react-router-dom';
export default withRouter(ViewUsers);
That's it now, your ViewUsers component has access to history object.
更新
2-在这个场景中,将所有的路由道具传递给你的组件,然后我们可以从组件中访问this.props.history,即使没有一个HOC
eg:
<Route path="/users" render={props => <ViewUsers {...props} />}
我可以通过使用bind()来实现这一点。我想点击索引中的一个按钮。Jsx,向服务器发布一些数据,评估响应,并重定向到success.jsx。以下是我的计算方法……
index.jsx:
import React, { Component } from "react"
import { postData } from "../../scripts/request"
class Main extends Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
this.postData = postData.bind(this)
}
handleClick() {
const data = {
"first_name": "Test",
"last_name": "Guy",
"email": "test@test.com"
}
this.postData("person", data)
}
render() {
return (
<div className="Main">
<button onClick={this.handleClick}>Test Post</button>
</div>
)
}
}
export default Main
request.js:
import { post } from "./fetch"
export const postData = function(url, data) {
// post is a fetch() in another script...
post(url, data)
.then((result) => {
if (result.status === "ok") {
this.props.history.push("/success")
}
})
}
success.jsx:
import React from "react"
const Success = () => {
return (
<div className="Success">
Hey cool, got it.
</div>
)
}
export default Success
通过在index中绑定这个到postData。jsx,我能够访问this.props.history在request.js…那么我就可以在不同的组件中重用这个函数,只是要确保我记得包含这个。构造函数()中的postData = postData.bind(this)。