Sanjeet Uppal
Sanjeet Uppal

Reputation: 39

Redirect after successful async action with react router v3

I've tried a few ways of going about this where in my action is do the dispatch(push) :

import LoginService from '../../services/login-service';

export const ActionTypes = {
  SET_LOGIN: 'SET_LOGIN',
}

export function getLogin(data, dispatch) {
  LoginService.getLoginInfo(data).then((response) => {
    const login = response.data;
    dispatch({
      type: ActionTypes.SET_LOGIN,
      login
    })
    // .then((res) => {
    //   dispatch(push('/'));
    // })
  })
}

I even saw something about using the render property on the route for react router.

Now I am trying to use renderIf based on whether my state is true or false but I can't seem to get props on this page successfully :

import React from 'react';
import renderIf from 'render-if';
import { Redirect } from 'react-router-dom';
import LoginHeader from '../../components/header/login-header';
import LoginPage from './login-page';

const LoginHome = props => (
  <div>
    {console.log(props)}
    {renderIf(props.loginReducer.status === false)(
      <div>
        <LoginHeader />
        <LoginPage />}
      </div>)}
    {renderIf(props.loginReducer.status === true)(
      <Redirect to="/" />,
    )}
  </div>
);

export default LoginHome;

Here is loginPage:

import React from 'react';
import { form, FieldGroup, FormGroup, Checkbox, Button } from 'react-bootstrap';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import { connect } from 'react-redux';
import { getLogin } from './login-actions';
import LoginForm from './form';
import logoSrc from '../../assets/images/logo/K.png';
import './login.scss'


class LoginPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      passwordVisible: false,
    }
    this.handleSubmit= this.handleSubmit.bind(this);
    this.togglePasswordVisibility= this.togglePasswordVisibility.bind(this);
  }

  togglePasswordVisibility() {
    this.setState((prevState) => {
      if (prevState.passwordVisible === false) {
        return { passwordVisible: prevState.passwordVisible = true }
      }
      else if (prevState.passwordVisible === true) {
        return { passwordVisible: prevState.passwordVisible = false }
      }
    })
  }

  handleSubmit(values) {
    this.props.onSubmit(values)
  }

  render () {
      return (
        <div id="background">
          <div className="form-wrapper">
             <img
              className="formLogo"
              src={logoSrc}
              alt="K"/>
              <LoginForm onSubmit={this.handleSubmit} passwordVisible={this.state.passwordVisible}
              togglePasswordVisibility={this.togglePasswordVisibility}/>
          </div>
        </div>
      )
  }
}

function mapStateToProps(state) {
  return {
    loginReducer: state.loginReducer,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    onSubmit: (data) => {
      getLogin(data, dispatch);
    },
  };
}

export default connect (mapStateToProps, mapDispatchToProps)(LoginPage);

Let me know if anything else is needed

Upvotes: 1

Views: 3876

Answers (1)

Kyle Richardson
Kyle Richardson

Reputation: 5645

Use the withRouter HoC from React Router to provide { match, history, location } to your component as follows;

import { withRouter } from "react-router";

...

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(LoginPage));

Modify getLogin to accept history as a third argument; export function getLogin(data, dispatch, history) { ... }

Now in the then method of your async action you can use history.push() or history.replace() to change your current location. <Redirect /> uses history.replace() internally.

You can read about the history module here. This is what is used internally by React Router.

EDIT: In response to your comment...

With your current setup you will need to pass history into getLogin through your mapDispatchToProps provided onSubmit prop.

function mapDispatchToProps(dispatch) {
  return {
    onSubmit: (data, history) => {
      getLogin(data, dispatch, history);
    },
  };
}

Your handleSubmit method will also need updated.

handleSubmit(values) {
  this.props.onSubmit(values, this.props.history)
}

Modified answer depending on how Router was set up I had to use hashHistory: react-router " Cannot read property 'push' of undefined"

Upvotes: 2

Related Questions