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.
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)
    }
};
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With