I have a login page component and I would like to redirect, after a successful login, from the action creator (thunk). It seem to work but while the URL changes correctly the page remains on the Login page.
here I import the history to be imported in the action creator:
// helpers/history.js
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;
here the shorten version of the 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 => {
...
and here the shorten version of the component to show how login is called and the imports
// 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);
here instead how browserRouter is implemented:
// 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>
...
I would recommend that you ditch this history
object entirely and handle your navigation from components which are inside of your BrowserRouter
context rather than through an action creator.
LoginForm
can access a contextual history
prop through withRouter
. It can access the credentials in the state as pass an isLoggedIn
prop through mapStateToProps
.
The render()
method of your LoginForm
would include a Redirect
component that is rendered conditionally depending on the isLoggedIn
prop, which will update when you dispatch
LOGIN_REQUEST_SUCCESS
.
Somehow map from state
to a boolean
prop isLoggedIn
. An example:
const mapStateToProps = (state) => ({
isLoggedIn: !!state.credentials.token
})
Conditional render:
{this.props.isLoggedIn && <Redirect to="/live-rewards" />}
I prefer this approach because it means that the log in page cannot be loaded at all if the user is already logged in.