来自 Action Creator 的 history.push() 将更改 URL 但不会导航到页面
history.push() from Action Creator will Change URL but will Not Navigate to Page
我有一个登录页面组件,我想在成功登录后从操作创建者 (thunk) 重定向。
它似乎可以工作,但是 URL 正确更改后页面仍保留在登录页面上。
这里我导入了要在action creator中导入的历史:
// helpers/history.js
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;
这里是 action creator 的简化版本:
// actions/session.js
import history from '../helpers/history';
export const login = (formData) => {
return (dispatch) => {
dispatch({type: LOGIN_REQUEST})
return fetch("http://localhost:3001/login", {
...
.then((user) => {
history.push('/live-rewards')
dispatch({
type: LOGIN_REQUEST_SUCCESS
})
})
.catch(err => {
...
这里是组件的缩短版本,用于显示如何调用登录和导入
// containers/LoginForm.js
import React, { Component } from 'react'
import { connect } from "react-redux";
import { Link } from 'react-router-dom'
import { login } from '../actions/session'
class LoginForm extends Component {
...
fetchOnSubmit = (e) => {
e.preventDefault()
this.props.login(this.state)
}
...
const mapDispatchToProps = dispatch => {
return {
login: (credentials) => {
return dispatch(login(credentials))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
此处改为 browserRouter 的实现方式:
// index.js
...
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
...
// app.js
...
<Router>
<Navbar toggle={toggle} />
<Sidebar isOpen={isOpen} toggle={toggle} />
<Switch>
<Route path='/live-rewards' component={Liverewards}/>
<Route path='/signin' component={Signin}/>
<Route path='/signup' component={Signup}/>
<Route path='/' exact component={Home}/>
</Switch>
</Router>
...
我建议您完全放弃这个 history
对象,并从 BrowserRouter
上下文中的组件处理导航,而不是通过动作创建者。
LoginForm
可以通过 withRouter
访问上下文 history
道具。它可以通过 mapStateToProps
.
传递 isLoggedIn
道具来访问状态中的凭据
LoginForm
的 render()
方法将包含一个 Redirect
组件,该组件根据 isLoggedIn
道具有条件地呈现,当您 dispatch
LOGIN_REQUEST_SUCCESS
.
以某种方式从 state
映射到 boolean
道具 isLoggedIn
。一个例子:
const mapStateToProps = (state) => ({
isLoggedIn: !!state.credentials.token
})
条件渲染:
{this.props.isLoggedIn && <Redirect to="/live-rewards" />}
我更喜欢这种方法,因为这意味着如果用户已经登录,则根本无法加载登录页面。
我有一个登录页面组件,我想在成功登录后从操作创建者 (thunk) 重定向。 它似乎可以工作,但是 URL 正确更改后页面仍保留在登录页面上。
这里我导入了要在action creator中导入的历史:
// helpers/history.js
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;
这里是 action creator 的简化版本:
// actions/session.js
import history from '../helpers/history';
export const login = (formData) => {
return (dispatch) => {
dispatch({type: LOGIN_REQUEST})
return fetch("http://localhost:3001/login", {
...
.then((user) => {
history.push('/live-rewards')
dispatch({
type: LOGIN_REQUEST_SUCCESS
})
})
.catch(err => {
...
这里是组件的缩短版本,用于显示如何调用登录和导入
// containers/LoginForm.js
import React, { Component } from 'react'
import { connect } from "react-redux";
import { Link } from 'react-router-dom'
import { login } from '../actions/session'
class LoginForm extends Component {
...
fetchOnSubmit = (e) => {
e.preventDefault()
this.props.login(this.state)
}
...
const mapDispatchToProps = dispatch => {
return {
login: (credentials) => {
return dispatch(login(credentials))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
此处改为 browserRouter 的实现方式:
// index.js
...
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
...
// app.js
...
<Router>
<Navbar toggle={toggle} />
<Sidebar isOpen={isOpen} toggle={toggle} />
<Switch>
<Route path='/live-rewards' component={Liverewards}/>
<Route path='/signin' component={Signin}/>
<Route path='/signup' component={Signup}/>
<Route path='/' exact component={Home}/>
</Switch>
</Router>
...
我建议您完全放弃这个 history
对象,并从 BrowserRouter
上下文中的组件处理导航,而不是通过动作创建者。
LoginForm
可以通过 withRouter
访问上下文 history
道具。它可以通过 mapStateToProps
.
isLoggedIn
道具来访问状态中的凭据
LoginForm
的 render()
方法将包含一个 Redirect
组件,该组件根据 isLoggedIn
道具有条件地呈现,当您 dispatch
LOGIN_REQUEST_SUCCESS
.
以某种方式从 state
映射到 boolean
道具 isLoggedIn
。一个例子:
const mapStateToProps = (state) => ({
isLoggedIn: !!state.credentials.token
})
条件渲染:
{this.props.isLoggedIn && <Redirect to="/live-rewards" />}
我更喜欢这种方法,因为这意味着如果用户已经登录,则根本无法加载登录页面。