Chr*_*ris 315 reactjs react-router react-router-v4
在当前版本的React Router(v3)中,我可以接受服务器响应并使用它browserHistory.push来转到相应的响应页面.但是,这在v4中不可用,我不确定处理它的适当方法是什么.
在此示例中,使用Redux,在用户提交表单时调用components/app-product-form.jsthis.props.addProduct(props).当服务器返回成功时,用户将进入购物车页面.
// 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
});
}
Run Code Online (Sandbox Code Playgroud)
如何从React Router v4的功能重定向到Cart页面?
Chr*_*ris 319
React Router v4与v3(及更早版本)根本不同,你不能browserHistory.push()像以前那样做.
如果您想了解更多信息,此讨论似乎相关:
- 创建新的
browserHistory将无法工作,因为<BrowserRouter>创建自己的历史记录实例,并侦听其中的更改.因此,不同的实例将更改URL但不更新<BrowserRouter>.browserHistory在v4中,反应路由器不会公开,仅在v2中.
相反,您有几个选项可以做到这一点:
withRouter高阶组件相反,您应该使用withRouter高阶组件,并将其包装到将推送到历史记录的组件.例如:
import React from "react";
import { withRouter } from "react-router-dom";
class MyComponent extends React.Component {
...
myFunction() {
this.props.history.push("/some/Path");
}
...
}
export default withRouter(MyComponent);
Run Code Online (Sandbox Code Playgroud)
查看官方文档了解更多信息:
你可以访问
history对象的属性和最近<Route>的match经withRouter高阶组件.withRouter将在每次路径更改时重新渲染其组件,并使用与<Route>渲染道具相同的道具:{ match, location, history }.
contextAPI使用上下文可能是最简单的解决方案之一,但作为实验性API,它不稳定且不受支持.仅在其他一切都失败时使用它.这是一个例子:
import React from "react";
import PropTypes from "prop-types";
class MyComponent extends React.Component {
static contextTypes = {
router: PropTypes.object
}
constructor(props, context) {
super(props, context);
}
...
myFunction() {
this.context.router.history.push("/some/Path");
}
...
}
Run Code Online (Sandbox Code Playgroud)
查看有关上下文的官方文档:
如果您希望应用程序稳定,请不要使用上下文.它是一个实验性的API,很可能会在未来的React版本中破解.
如果您坚持使用上下文尽管存在这些警告,请尝试将上下文的使用隔离到一个小区域,并尽可能避免在可能的情况下直接使用上下文API,以便在API更改时更容易升级.
Ole*_*sky 260
您可以使用history组件外部的方法.请尝试以下方式.
首先,创建一个history使用历史包的对象:
// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Run Code Online (Sandbox Code Playgroud)
然后把它包起来<Router>(请注意,你应该使用import { Router }而不是import { BrowserRouter as Router }):
// src/index.jsx
// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/login">Login</Link></li>
</ul>
<Route exact path="/" component={HomePage} />
<Route path="/login" component={LoginPage} />
</div>
</Router>
</Provider>,
document.getElementById('root'),
);
Run Code Online (Sandbox Code Playgroud)
从任何地方更改您当前的位置,例如:
// src/actions/userActionCreators.js
// ...
import history from '../history';
export function login(credentials) {
return function (dispatch) {
return loginRemotely(credentials)
.then((response) => {
// ...
history.push('/');
});
};
}
Run Code Online (Sandbox Code Playgroud)
UPD:您还可以在React Router FAQ中看到略有不同的示例.
Mic*_*ski 23
我就这样做了:
import React, {Component} from 'react';
export default class Link extends Component {
constructor(props) {
super(props);
this.onLogout = this.onLogout.bind(this);
}
onLogout() {
this.props.history.push('/');
}
render() {
return (
<div>
<h1>Your Links</h1>
<button onClick={this.onLogout}>Logout</button>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
使用this.props.history.push('/cart');重定向到购物车页面将被保存在历史记录对象.
享受,迈克尔.
小智 21
根据React Router v4文档 - Redux Deep Integration会话
需要深度整合:
"能够通过调度行动导航"
但是,他们建议这种方法作为"深度整合"的替代方案:
"而不是分派行动进行导航,您可以将提供的历史记录对象传递给您的行为并在那里进行导航."
因此,您可以使用withRouter高阶组件包装组件:
export default withRouter(connect(null, { actionCreatorName })(ReactComponent));
这会将历史API传递给道具.所以你可以调用动作创建者将历史作为参数传递.例如,在ReactComponent中:
onClick={() => {
this.props.actionCreatorName(
this.props.history,
otherParams
);
}}
Run Code Online (Sandbox Code Playgroud)
然后,在你的actions/index.js里面:
export function actionCreatorName(history, param) {
return dispatch => {
dispatch({
type: SOME_ACTION,
payload: param.data
});
history.push("/path");
};
}
Run Code Online (Sandbox Code Playgroud)
Saa*_*ran 19
在React Router 4中最简单的方法就是使用
this.props.history.push('/new/url');
Run Code Online (Sandbox Code Playgroud)
但是要使用此方法,现有组件应该可以访问history对象.我们可以通过访问
如果您的组件Route直接链接,那么您的组件已经可以访问history对象.
例如:
<Route path="/profile" component={ViewProfile}/>
Run Code Online (Sandbox Code Playgroud)
这里ViewProfile有访问权限history.
如果没有Route直接连接.
例如:
<Route path="/users" render={() => <ViewUsers/>}
Run Code Online (Sandbox Code Playgroud)
然后我们必须使用withRouter更高级的功能来扭曲现有组件.
内部 ViewUsers组件
import { withRouter } from 'react-router-dom';
export default withRouter(ViewUsers);
就是这样,你的ViewUsers组件可以访问history对象.
UPDATE
2- 在这种情况下,将所有路径传递props给您的组件,然后this.props.history即使没有a ,我们也可以从组件访问HOC
例如:
<Route path="/users" render={props => <ViewUsers {...props} />}
Run Code Online (Sandbox Code Playgroud)
Khr*_*rok 18
讨厌的问题,花了我很多时间,但最终,我这样解决了:
包裹您的容器withRouter并将历史记录传递给您的 mapDispatchToProps功能.在操作中使用history.push('/ url')进行导航.
行动:
export function saveData(history, data) {
fetch.post('/save', data)
.then((response) => {
...
history.push('/url');
})
};
Run Code Online (Sandbox Code Playgroud)
容器:
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));
Run Code Online (Sandbox Code Playgroud)
这对React Router v4.x有效.
小智 7
this.context.history.push 不管用.
我成功地推动了这样的工作:
static contextTypes = {
router: PropTypes.object
}
handleSubmit(e) {
e.preventDefault();
if (this.props.auth.success) {
this.context.router.history.push("/some/Path")
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你将道具传递给你的thunk.所以你可以简单地打电话
props.history.push('/cart')
Run Code Online (Sandbox Code Playgroud)
如果不是这种情况,您仍然可以从组件中传递历史记录
export function addProduct(data, history) {
return dispatch => {
axios.post('/url', data).then((response) => {
dispatch({ type: types.AUTH_USER })
history.push('/cart')
})
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
I offer one more solution in case it is worthful for someone else.
I have a history.js file where I have the following:
import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history
Run Code Online (Sandbox Code Playgroud)
Next, on my Root where I define my router I use the following:
import history from '../history'
import { Provider } from 'react-redux'
import { Router, Route, Switch } from 'react-router-dom'
export default class Root extends React.Component {
render() {
return (
<Provider store={store}>
<Router history={history}>
<Switch>
...
</Switch>
</Router>
</Provider>
)
}
}
Run Code Online (Sandbox Code Playgroud)
Finally, on my actions.js I import History and make use of pushLater
import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)
Run Code Online (Sandbox Code Playgroud)
This way, I can push to new actions after API calls.
Hope it helps!
注意不要使用react-router@5.2.0或react-router-dom@5.2.0with history@5.0.0。URL 将在history.push或任何其他推送到历史记录说明之后更新,但导航不适用于react-router. 用于npm install history@4.10.1更改历史版本。请参阅升级到 v 5 后反应路由器不工作。
我认为这个问题是在推动历史发生时发生的。例如,<NavLink to="/apps">在 NavLink.js 中遇到一个消耗<RouterContext.Consumer>. context.location当推送到历史发生时,正在更改为具有操作和位置属性的对象。因此currentLocation.pathname为 null 以匹配路径。
现在,通过react-router v5,您可以使用useHistory生命周期挂钩,如下所示:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请访问:https : //reacttraining.com/react-router/web/api/Hooks/usehistory
小智 5
我在同一主题上遇到了困难。我正在使用react-router-dom 5、Redux 4 和BrowserRouter。我更喜欢基于函数的组件和钩子。
你像这样定义你的组件
import { useHistory } from "react-router-dom";
import { useDispatch } from "react-redux";
const Component = () => {
...
const history = useHistory();
dispatch(myActionCreator(otherValues, history));
};
Run Code Online (Sandbox Code Playgroud)
你的动作创建者正在关注
const myActionCreator = (otherValues, history) => async (dispatch) => {
...
history.push("/path");
}
Run Code Online (Sandbox Code Playgroud)
如果不需要异步,您当然可以拥有更简单的动作创建器
| 归档时间: |
|
| 查看次数: |
410859 次 |
| 最近记录: |