0

I was searching for a simple Login/Registration System and stumbled about this tutorial:

http://jasonwatmore.com/post/2017/09/16/react-redux-user-registration-and-login-tutorial-example

I tried it and added a real mongoDB Backend to remove the Mock-Backend. It was my first time doing Redux, but after a lot of struggle everything is working finde now! You can see the result here :

https://genko.de/login

Just one thing is not working at all and i have no clue how to solve it. Since I want to avoid bootstrap, I have a big problem with the error handling.

I want to display a snackbar from Material-Ui for following cases:

  • Username or Password is invalid
  • Successfull Logged in
  • Username is already taken (Registration)

In fact there are already some actions and reducers in my redux files, but to be honest, I just copied them from the tutorial and I have no clue how to work with them.

Following function is triggered by the Login button:

  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))
      }
}

And this is my login function (user.actions):

function login(username, password) {
return dispatch => {
    dispatch(request({ username }));

    userService.login(username, password)
        .then(
            user => {
                dispatch(success(user));
                history.goBack();
            },
            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 } }
}

alert.actions:

import { alertConstants } from '../_constants';
export const alertActions = {
    success,
    error,
    clear
};

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

function error(message) {
    return { type: alert, message };
}

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

And finally my alert.constants:

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

Do you have some hints for me or suggestions?

Best regards :)

EDIT:

I forgot to show you my NodeJS Global Error Handler Middleware from this follow up tutorial to replace the face-backend:

    module.exports = errorHandler;

function errorHandler(err, req, res, next) {
    if (typeof (err) === 'string') {
        // custom application error
        return res.status(400).json({ message: err });
    }

    if (err.name === 'ValidationError') {
        // mongoose validation error
        return res.status(400).json({ message: err.message });
    }

    if (err.name === 'UnauthorizedError') {
        // jwt authentication error
        return res.status(401).json({ message: 'Invalid Token' });
    }

    // default to 500 server error
    return res.status(500).json({ message: err.message });
    }
Martin Seubert
  • 412
  • 1
  • 9
  • 30

1 Answers1

1

you need to have an entries in your reducer for LOGIN_SUCCESS and LOGIN_FAILURE that will set the state in the redux store to something that you can use back in your component.

function reducer(state = { status: ''}, action) {
  switch (action.type) {
    case 'LOGIN_SUCCESS':
      return { status: 'LOGGED_IN'}
    ... ETC  
    default:
      return state
  }
}

Then via mapStateToProps you will map the state of the redux store to props of the component and be able to use it like -

const mapStateToProps = (state) => ({
   status: state.status
})

this.props.status // LOGGED_IN

andy mccullough
  • 6,646
  • 6
  • 24
  • 39