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