Login logout using react redux

  0 comments
Share

Create a component for login screen. In which we will make text field for username and password. Below is the code for full component for login page.

import React, { Component } from "react";
import { Link } from 'react-router-dom';
import { userActions } from '../actions/user.actions';
import { connect } from 'react-redux';

class LoginUserPage extends Component {
    constructor(props) {
        super(props);

        // reset login status
        this.props.dispatch(userActions.logout());

        this.state = {
            username: '',
            password: '',
            submitted: false
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange(e) {
        const { name, value } = e.target;
        this.setState({ [name]: value });
    }
    handleSubmit(e) {
        e.preventDefault();

        this.setState({ submitted: true });
        const { username, password } = this.state;
        const { dispatch } = this.props;
        if (username && password) {
            dispatch(userActions.login(username, password));
        }
    }
    render() {
        const { loggingIn } = this.props;
        const { username, password, submitted } = this.state;
        return (
		  <div className="container">
            <div className="col-md-6 col-md-offset-3">
                <h2>Login</h2>
                <form name="form" onSubmit={this.handleSubmit}>
                    <div className={'form-group' + (submitted && !username ? ' has-error' : '')}>
                        <label htmlFor="username">Username</label>
                        <input type="text" className="form-control" name="username" value={username} onChange={this.handleChange} />
                        {submitted && !username &&
                            <div className="help-block">Username is required</div>
                        }
                    </div>
                    <div className={'form-group' + (submitted && !password ? ' has-error' : '')}>
                        <label htmlFor="password">Password</label>
                        <input type="password" className="form-control" name="password" value={password} onChange={this.handleChange} />
                        {submitted && !password &&
                            <div className="help-block">Password is required</div>
                        }
                    </div>
                    <div className="form-group">
                        <button className="btn btn-primary">Login</button>
                        {loggingIn &&
                            <img src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
                        }
                        <Link to="/register" className="btn btn-link">Register</Link>
                    </div>
                </form>
            </div>
		  </div>
        );
    }
}
 
function mapStateToProps(state) {
    const { loggingIn } = state.authentication;
    return {
        loggingIn
    };
}
const connectedLoginPage = connect(mapStateToProps)(LoginUserPage);
export { connectedLoginPage as LoginUserPage }; 

In above code we used user login action adn logout action for that we have written code in user.actions.js file which we will place in action folder. Below is the code for user.actions.js file.

import { userConstants } from '../constants/user.constants.js';
import { userService } from '../services/user.service';
import { alertAction } from './alert.action';
import { createBrowserHistory } from 'history';

export const userActions = {
    login,
    logout,
};
export const history = createBrowserHistory();
function login(username, password) {
    return dispatch => {
        dispatch(request({ username }));

        userService.login(username, password)
            .then(
                user => { 
			        let userData = JSON.parse(localStorage.getItem('user'));
					if('message' in userData){
   				      //console.log('user'+ userData.message);
                      dispatch(failure(userData.message.toString()));
                      dispatch(alertAction.error(userData.message.toString()));
					}else{
                      dispatch(success(user));
                      history.push('/');
					}
                },
                error => {
                    dispatch(failure(error.toString()));
                    dispatch(alertActions.error(error.toString()));
                }
            );
    };

    function request(user) { return { type: userConstants.LOGIN_REQUEST, user } }
    function success(user) { return { type: userConstants.LOGIN_SUCCESS, user } }
    function failure(error) { return { type: userConstants.LOGIN_FAILURE, error } }
}

function logout() {
    userService.logout();
    return { type: userConstants.LOGOUT };
}

In above code we used Constants which we will place in user.constants.js file

export const userConstants = {

    LOGIN_REQUEST: 'USERS_LOGIN_REQUEST',
    LOGIN_SUCCESS: 'USERS_LOGIN_SUCCESS',
    LOGIN_FAILURE: 'USERS_LOGIN_FAILURE',
    
    LOGOUT: 'USERS_LOGOUT',

};

Place below code in alert.constants.js file

export const alertConstants = {
    SUCCESS: 'ALERT_SUCCESS',
    ERROR: 'ALERT_ERROR',
    CLEAR: 'ALERT_CLEAR'
};

Place below code in alert.actions.js file

import { alertConstant } from '../constants/alert.constants';

export const alertActions = {
    success,
    error,
    clear
};

function success(message) {
    return { type: alertConstant.SUCCESS, message };
}

function error(message) {
    return { type: alertConstant.ERROR, message };
}

function clear() {
    return { type: alertConstant.CLEAR };
}

In login function we are using another function to call the login API. Below is the code to place in user.service.js file

I have used axios library to call API. So you will need to install axios library

Command to install axios library

npm install --save axios
import axios from 'axios';

export const userService = {
    login,
    logout,
};

function login(username, password) {
    const requestOptions = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username, password })
    };

	return	axios.get('https://drupalchamp.org/session/token').then(result => {
		console.log('csrfToken'+ result.data);
		  if (200 === result.status) {
			const csrfToken = result.data;
			return fetch('https://drupalchamp.org/user/login?_format=json', {
			  method: 'POST',
			  headers: {
				'Content-Type': 'application/json',
				'X-CSRF-Token': csrfToken
			  },
			  body: JSON.stringify({
				'name':username,
				'pass' : password,
			  }),
			})
			.then(response => response.json())
			.then(data =>{
				console.log('sddddsuccess', data);
				localStorage.setItem('user', JSON.stringify(data));
				return data;
				}
			);				  
		}
	});
}

function logout() {
    // remove user from local storage to log user out
    localStorage.removeItem('user');
}

Make index.js file in src directory and place the below code

import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap.bundle.min';
import React from "react";
//import ReactDOM from "react-dom";
import {Main} from "./Main";

import { render } from 'react-dom';

import { Provider } from 'react-redux';
import { store } from 'store';

render(
  
, document.getElementById("root") ); Place below code in store.js file import { createStore, applyMiddleware } from 'redux'; import thunkMiddleware from 'redux-thunk'; import { createLogger } from 'redux-logger'; import rootReducer from '../reducers/authentication.reducer'; const loggerMiddleware = createLogger(); export const store = createStore( rootReducer, applyMiddleware( thunkMiddleware, loggerMiddleware ) ); Place below code in Main.js file import React, { Component } from "react"; import {Navigation} from "./js/components/Navigation"; import Footer from "./js/components/Footer"; import {LoginUserPage} from "./js/pages/LoginUserPage"; import { alertActions } from './js/_actions'; import { history } from './js/_helpers'; import { connect } from 'react-redux'; library.add(faIgloo) class Main extends Component { constructor(props) { super(props); const { dispatch } = this.props; history.listen((location, action) => { // clear alert on location change dispatch(alertActions.clear()); }); } render() { const { alert } = this.props; return ( <Router history={history}> <div> <Navigation /> <div className="content"> {alert.message && <div className={`alert ${alert.type}`}>{alert.message}</div> } <Switch> <Route exact path="/" render={() => <Home />} /> <Route exact path="/login" render={() => <LoginUserPage />} /> <Route render={() => <Page404 />} /> </Switch> </div> <Footer /> <ScrollUpButton /> </div> </Router> ); } } function mapStateToProps(state) { const { alert } = state; return { alert }; } const connectedApp = connect(mapStateToProps)(Main); export { connectedApp as Main };

Place below code in authentication.reducer.js file within reducers directory

import { userConstants } from '../constants/user.constants';

let user = JSON.parse(localStorage.getItem('user'));
const initialState = user ? { loggedIn: true, user } : {};

export function authentication(state = initialState, action) {
  switch (action.type) {
    case userConstants.LOGIN_REQUEST:
      return {
        loggingIn: true,
        user: action.user
      };
    case userConstants.LOGIN_SUCCESS:
      return {
        loggedIn: true,
        user: action.user
      };
    case userConstants.LOGIN_FAILURE:
      return {};
    case userConstants.LOGOUT:
      return {};
    default:
      return state
  }
}

In navigation component I am showing login logout link for user which will be change upon user state

import React, { Component, Fragment } from "react";
import logo from './../../logo.png';
import { pushPath } from 'redux-simple-router';
import ReactDOM from "react-dom";
import { Navbar, Nav , NavDropdown } from "react-bootstrap";
import { BrowserRouter as Router, Route ,NavLink } from "react-router-dom";
import { withRouter } from "react-router";
import { connect } from 'react-redux';

import $ from 'jquery';
class Navigation extends React.Component {
      constructor(props) {
        super(props);
        let user = JSON.parse(localStorage.getItem('user')) || [];
        this.state = {
            user: user
        };		
    }
  render() {
    console.log('sdddddd546'+JSON.stringify(this.state.user));

    $('#header_area .navbar-light .navbar-collapse').removeClass('show');
    $('#header_area .navbar-light .navbar-collapse ul li a').on('click', function(){
	  $('#header_area .navbar-light .navbar-collapse').removeClass('show');
    });
	let user = false;

	let userdata = this.props.user;
	if((null == userdata) || (typeof userdata == 'undefined')){
		user = false;
	}else{
      user = true;
	  console.log('sddddddxzx546'+this.props.user);

	}
  	

    return (
	  <div id="whole_header_area">
		<div id="header_area" className="container">
		
		  <nav className="navbar navbar-expand-lg navbar-light">
			<NavLink className="navbar-brand" exact to="/"><img alt="" src={logo} className="d-inline-block align-top" /></NavLink>
			<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
			  <span className="navbar-icon"></span>
			  <span className="navbar-icon"></span>
			  <span className="navbar-icon"></span>
			</button>
	  
			<div className="collapse navbar-collapse" id="navbarSupportedContent">
			  <ul className="navbar-nav mr-n1">
				<li className="nav-item"><NavLink className="nav-link" exact to="/">Home</NavLink></li>
				<li className="nav-item">
					{user  ?  <NavLink className="nav-link"  to="/login">Logout</NavLink> : <NavLink className="nav-link"  to="/login">Login</NavLink>}
				</li>
				
			  </ul>
			</div>
		 </nav>

	 </div>
	</div>
    )
  }
}

function mapStateToProps(state) {
    const { users, authentication } = state;
    const { user } = authentication;
    return {
        user
    };
}

const connectedHomePage = connect(mapStateToProps)(Navigation);
export { connectedHomePage as Navigation }; 

Add new comment