Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect to Home after Login on React Redux Application

Tags:

I am learning React Redux with Create-React-App

I am having trouble with the logic of stores, reducers, actions ect.

I have a simple login page (some JSX omitted to make it simpler to read)

Login.js

import React, { Component } from "react";
import { connect } from "react-redux";
import * as actions from '../../actions';
import Logo from "../img/image-center.png";
import "./login.css";


class Login extends Component {
  constructor(props){
    super(props);
    this.state = {
      errorMsg : ""
    };
    this.loginClicked = this.loginClicked.bind(this);   
    console.log("loggedIn:", this.props.login);
  }

  loginClicked() {
    try {
      this.props.loginUser(this.refs.email.value, this.refs.password.value)
      .then(() => {
        console.log("thisprops", this.props);        
      });
    }
    catch(ex){
      this.state.errorMsg = "Unable to connect to server";
      console.log("error", ex);
    }
  }

  render() {
    return (

      <div className="login-bg">
        <div className="container signForm">
            <div className="col s12 l6 login-form">
              <p className="center-align">Login to Trade Portal</p>
              <form>
                <div className="row">
                  <div className="input-field">
                    <input id="email" type="email" className="validate" ref="email" />
                    <label htmlFor="email">Email</label>
                  </div>
                </div>
                <div className="row">
                  <div className="input-field">
                    <input id="password" type="password" className="validate" ref="password" />
                    <label htmlFor="password">Password</label>
                  </div>
                </div>
                <div className="row">
                  <button
                    className="btn waves-effect waves-light"
                    type="button"
                    name="action"
                    onClick={this.loginClicked}
                    >
                    Submit
                  </button>
                  <a href="/subcontractor" className="register">
                    Register here
                  </a>
                </div>
                <div className="row"><div style={{textAlign: "center", color:"red"}}>{this.props.login.message}</div></div>   

              </form>
            </div>
          </div>
        </div>
      </div>
    );
  }
}


function mapStateToProps({login}){
  return { login } ;
}

export default connect(mapStateToProps, actions)(Login);

As you can see the LoginClick fucntion calls a prop loginUser which is derived using connect (and actually calls my Action Login method)

actions\index.js

import axios from "axios";
import { FETCH_USER, LOGIN_USER, LOGIN_FAILED } from "./types";


export const fetchUser = () => async dispatch => {
  const res = await axios.get("/api/Account/GetUser");
  dispatch({ type: FETCH_USER, payload: res.data });
};

export const loginUser = (username, password) => async dispatch => {
    try {
        const res = await axios.post("/api/Account/Login", {username: username, password: password, persistant: false });
        const message = res.data ? "" : "Incorrect username or password";
        dispatch({ type: LOGIN_USER, payload: { success: res.data, message: message } });
    }
    catch(ex){
        console.log("Login Failed:", ex);
        dispatch({ type: LOGIN_FAILED, payload: { success: false, message: "Unable to connect to authentication server" } });
    }
}

The above code calls my Server and logs in the user, when succesful it is read in the loginReducer.js

import { LOGIN_USER, LOGIN_FAILED } from "../actions/types";

export default function(state = null, action) {
  console.log(action);
  switch (action.type) {
    case LOGIN_USER:      
      return { success: action.payload.success, message: action.payload.message };
      break;
    case LOGIN_FAILED:
      return { success: false, message: action.payload.message };
      break;
      default:
    return { success: false, message: ""};
  }
}

Now my question is where and how do I redirect the user on succeful Logging in to the home page? "/Home"

I am hoping I can do it in Login.js somewhere, as one day I may want to have 2 login routes (Ie If logging in from a header it may not redirect to home, but when logging in from Login.js it should log into home). Therefore I dont think this action should go in the Action or Reducer. But I am unsure how I can bind it in Login.js so when Login successfull, redirect

like image 870
Michael Avatar asked Jan 17 '18 06:01

Michael


People also ask

How do I redirect after login?

Navigate to LoginWP > Redirections. Setting up redirection rules with the LoginWP plugin. There are several settings you can change here but look to the All Other Users heading and the Login URL option. Change this to the URL you want and click Save Changes.


1 Answers

Possible ways-

1- Redirect from loginClicked method after successful login (inside .then), Like this:

loginClicked() {
    try {
      this.props.loginUser(this.refs.email.value, this.refs.password.value)
      .then(() => {
          this.props.history.push('/home');       
      });
    }
    catch(ex){
      this.state.errorMsg = "Unable to connect to server";
      console.log("error", ex);
    }
}

2- Or another option is put the check inside render method, whenever any change happens to store, it will re-render the component and if you find the success == true redirect to home page, Like this:

render(){

    if(this.props.success)
        return <Redirect to="/home" />

    return (....)
}

If you follow the first approach then you need to put the check inside componentDidMount method also, if user want to open login page after successful login, redirect to Home page. You are maintaining the login session by bool success check that bool value.

componentDidMount(){
   if(this.props.success) {
      this.props.history.push('/home');
   }
}

Suggestion:

Avoid using string refs, as per DOC:

If you worked with React before, you might be familiar with an older API where the ref attribute is a string, like "textInput", and the DOM node is accessed as this.refs.textInput. We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. If you’re currently using this.refs.textInput to access refs, we recommend the callback pattern instead.

like image 181
Mayank Shukla Avatar answered Sep 20 '22 12:09

Mayank Shukla