tl;dr: In the LoginForm, this.props is undefined despite my passing in actions in mapDispatchToProps.
I've set breakpoints in the connect function, and the action is making it into the connect function, but for whatever reason, in the handleSubmit function, this.props is undefined.
I'm stumped.
I have a separate 'SignUp' flow that's basically identical to what I have below, and it works perfectly.
I essentially copy pasted the sign up code, and renamed everything "login", and modified things slightly and for whatever reason this.props is undefined, even though what I'm passing into mapDispatchToProps seems to be correct.
The component:
import React from 'react';
import { connect } from 'react-redux';
import { loginSubmit, loginUpdateField } from '../../redux/actions/login.actions';
import { TextInput } from '../../stories/TextInput';
import { Button } from '../../stories/Button';
export class LoginForm extends React.Component {
// eslint-disable-next-line
constructor(props) {
super(props);
}
handleSubmit(event) {
event.preventDefault();
console.log('Props: ', this.props); // UNDEFINED!!!!!!
}
handleUpdateField(field, value) {
// this.props.updateField(field, value);
}
render() {
return (
<form style={{ 'WebkitPerspective': '1000' }}>
<TextInput label="Username" id="username" /> <br />
<TextInput label="Password" id="password" type="password" /> <br /><br />
<Button disabled={false} primary size="medium" onClick={this.handleSubmit.bind(this)} label="Ready for Takeoff" />
<Button disabled={false} size="medium" onClick={() => alert} label="Cancel" />
</form>
);
}
}
export default connect(
null,
{ loginSubmit, loginUpdateField }
)(LoginForm);
The action:
export const loginSubmit = (fieldValues) => {
return dispatch => {
dispatch(loginSubmitBegin);
let errors = isFormValid(fieldValues);
if (!errors.formValid) {
dispatch(loginErrors(errors));
} else {
axios
.post(`https://api.mydomain.io/login`, fieldValues, { headers: { "Access-Control-Allow-Origin": "*", } })
.then(res => {
dispatch(loginSuccess({ username: 'testuser' }));
})
.catch(err => {
handleErr(err.response.data.error);
});
}
}
};
The reducers:
const initialState = {
loginStatus: 'not_started',
fieldValues: {
username: '',
password: '',
},
errors: {
formValid: false,
username: [],
password: [],
}
};
export default function (state = initialState, action) {
switch (action.type) {
case 'LOGIN_UPDATE_FIELD':
let newState = {
...state,
};
newState.fieldValues[action.payload.fieldName] = action.payload.fieldValue;
return newState;
case 'LOGIN_SUBMIT_BEGIN':
return {
...state,
signupStatus: 'pending'
};
case 'LOGIN_ERRORS':
return {
...state,
signupStatus: 'errors',
errors: action.payload
};
case 'LOGIN_SUCCESS':
return {
...state,
signupStatus: 'success'
};
default:
return state;
}
}
Combined Reducer:
import { combineReducers } from 'redux';
import signup from './signup.reducers';
import user from './user.reducers';
import login from './login.reducers';
export default combineReducers({ login, user, signup});
LoginPage.js
import React from 'react';
import PropTypes from 'prop-types';
import { LoginForm } from '../features/LoginForm';
import './signup.css';
export const LoginPage = () => {
return (
<article>
<section>
<h2>Login!!</h2> <br /> <br />
<LoginForm />
</section>
</article>
);
};
LoginPage.propTypes = {
user: PropTypes.shape({})
};
LoginPage.defaultProps = {
user: null,
};