Redux action dispatch not working
Asked Answered
A

2

5

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.

Able answered 30/11, 2017 at 2:9 Comment(6)
does your page reloads after you click on submit ?Bootle
No, I have e.preventDefault(); in the handleLogin() method which I forgot to put with the questionJoann
all you have to do is change dispatch(requestLogin); to dispatch(requestLogin()); and may be pass the required data to action.Bootle
@Bootle this made it work! Thanks a lot! Can you please create an answer?Joann
@Ol' Reliable got the same issue. any suggestion for solution??Anastomosis
@Vikash.777 As @Bootle mentioned, the right way is to change dispatch(requestLogin); to dispatch(requestLogin(email, password);. Let me know if it still doesn't work for you.Joann
P
8

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)
    }
};
Petra answered 30/11, 2017 at 3:27 Comment(4)
I tried this and it still doesn't work, no errors but exact same behaviour as before (API going through but dispatch not working)Joann
Yeah, I forgot that.Petra
Is it working now ? I do have same problem but not workingNatator
@ArepalliPraveenkumar lol. came 3 years later to ask if it's still workingCastera
H
0

You should definitely try using e.stopPropagation(). If other stuff inside the function works while dispatch not, then you can try this. It worked for me.

Hadrian answered 19/2 at 19:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.