Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux action dispatch not working

I'm trying to dispatch an action when the user submits a form. Let's say I have a submit button that triggers an onSubmit event on the form (and eventually will show a spinner icon while the form request is being processed but at this point, the submit button just shows a true or false value representing whether or not the spinner is being shown).

LoginPage.js

import React from 'react';
import { Link } from 'react-router-dom';

export class LoginPage extends React.Component {
  constructor(props) {
    super(props);
    this.handleLogin = this.handleLogin.bind(this);
  }

  handleLogin(e) {
    e.preventDefault();
    let email = document.getElementById('userEmail').value;
    let password = document.getElementById('userPassword').value;
    this.props.loginHandler(email, password);
  }

  render() {
    return (
      <form onSubmit={ this.handleLogin }>
        <input type="submit" value={ this.props.requestingLogin } />
      </form>
    );
  }
}

export default LoginPage;

LoginPageContainer.js

import React from 'react';
import { connect } from 'react-redux';
import LoginPage from '../../components/login/LoginPage';
import { loginUser } from '../../actions';

export class LoginPageContainer extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <LoginPage requestingLogin={ this.props.requestingLogin } loginHandler={ this.props.loginUser } />
        );
    }
}

const mapStateToProps = state => {
    const { loginUserReducer } = state;
    return {
        requestingLogin: loginUserReducer.isRequestingLogin,
    };
};

const mapDispatchToProps = dispatch => {
    return {
        loginUser: (email, password) => { 
            dispatch(loginUser(email, password));
        }
    }
};


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

index.js in actions/

export const REQUEST_LOGIN = 'REQUEST_LOGIN';
function requestLogin() {
  return {
    type: REQUEST_LOGIN,
  };
};

export const loginUser = (email, password) => {
    return dispatch => {
        // this works because when the button is clicked,
        // I can successfully console log in here.
        dispatch(requestLogin); // THIS DISPATCH IS NOT WORKING
        // API call here...
    }
};

index.js in reducers/

import { combineReducers } from 'redux';
import { REQUEST_LOGIN } from '../actions';

const initialLoginState = {
    isRequestingLogin: false,
};

function loginUserReducer(state = initialLoginState, action) {
    switch(action.type) {
        case REQUEST_LOGIN:
            return Object.assign({}, state, { isRequestingLogin: true });
        default:
            console.log('returned from default');
            return state;
    }
}

const allReducers = combineReducers({
    loginUserReducer,
});

export default allReducers;

What's weird is that my API call that I have after the dispatch() inside loginUser() works but the dispatch() doesn't work.

I've seen many tutorials online and my code matches what I've seen but for some reason I can't figure out why dispatch the action is not working. Any help would be greatly appreciated.

like image 725
Ol' Reliable Avatar asked Mar 08 '23 11:03

Ol' Reliable


1 Answers

The problem is here:

const mapDispatchToProps = dispatch => {
    return {
        loginUser: (email, password) => { 
            dispatch(loginUser(email, password)); [DISPATCH ACTION]
        }
    }
};

So loginUser is a function that take email, password and call dispatch(loginUser(email, password))

But loginUser(email, password) doesn't return an action, instead, it returns a function.

export const loginUser = (email, password) => {
     return dispatch => {
         // this works because when the button is clicked,
         // I can successfully console log in here.
         dispatch(requestLogin); // THIS DISPATCH IS NOT WORKING
         // API call here...
      }
};

So the line [DISPATCH ACTION] doesn't dispatch an action but dispatch a function instead.

To make it correct, you can change like following:

const mapDispatchToProps = dispatch => {
    return {
        loginUser: (email, password) => {
             loginUser(email, password)(dispatch);
        }
    }
};

So, loginUser returns a function, you call it with dispatch as a parameter. But it doesn't seem to be pretty. How to do it correctly?

export const loginUser = dispatch => {
    return (email, password) => {
        // this works because when the button is clicked,
        // I can successfully console log in here.
        dispatch(requestLogin()); // THIS DISPATCH IS NOT WORKING
        // API call here...
    }
};

And in mapDispatchToProps:

const mapDispatchToProps = dispatch => {
    return {
        loginUser: loginUser(dispatch)
    }
};
like image 53
Daniel Tran Avatar answered Mar 17 '23 02:03

Daniel Tran