Hey everyone so I am in the works of creating a simulation of a user logging in. I am using redux logger and my state values that is logged is always the value I want to see however, when I am console.log(this.props)
I always get back undefined. My reducer has a state values that I have defined and have passed in as defaults. I am not sure why I am getting back undefined and just can't figure it out. Here is my code. Any help would be much appreciated I need to access these values but having it undefined does not work out.
I am going to condense down the boiler plate stuff like import statements etc. Also once again for context. All I am trying to do is inside of my component be able to access my state values that are defined inside of my reducer. For example, one of them is isLoginPending. When I am console.logging this.props.isLoginPending I would hope to either get the default value or the new Object.assigned value and not undefined. That is my ideal goal is to get a value inside of my component that is not undefined.
Here is my component
render() {
let {email, password} = this.state;
console.log("PROPS*****" + this.props.isLoginPending);
return (
<div className="form-wrapper" >
<form onSubmit={this.submit} name="login-form">
<label htmlFor="login-form">Email</label>
<input onChange={this.changedEmail} type="email" />
<br />
<label htmlFor="login-form"> Password </label>
<input onChange={this.changedPassword} type="password" />
<button type="submit">Login </button>
</form>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
isLoginPending: state.isLoginPending,
isLoginSuccess: state.isLoginSuccess,
isloginError: state.isloginError
}
}
const mapDispatchToProps = (dispatch) => {
return {
login: (email, password) => dispatch(login(email ,password))
};
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
Reducer
export default function (state = {
isLoginPending: false,
isLoginSuccess: false,
isLoginError: null
}, action)
{
switch(action.type) {
case constants.LOGIN_SUCCESS:
console.log("state" + state.isLoginPending);
return Object.assign({}, state, {isLoginSuccess: action.isLoginSuccess})
case constants.LOGIN_PENDING:
return Object.assign({}, state, {isLoginPending: action.isLoginPending})
case constants.LOGIN_ERROR:
return Object.assign({}, state, {isLoginError: action.isLoginError})
default:
return state
}
}
Actions
export const login = (email, password) => {
return dispatch => {
dispatch(loginPending(true));
dispatch(loginSuccess(false));
dispatch(loginError(null));
sendLoginRequest(email, password, error => {
dispatch(loginPending(false));
if(!error) {
dispatch(loginSuccess(true));
} else {
dispatch(loginError(error));
}
});
}
}
const sendLoginRequest = (email, password, callback) => {
setTimeout(() => {
if(email === '[email protected]' && password === 'password') {
return callback(null);
}
else {
return callback(new Error("invalid email or password"));
}
}, 1000)
}
** edit **
const createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<App />
</Provider>
root reducer that is passed into store
const rootReducer = combineReducers({
loginForm: emailReducer
});
export default rootReducer;
The "Cannot read property 'props' of undefined" error occurs when a class method is called without having the correct context bound to the this keyword. To solve the error, define the class method as an arrow function or use the bind method in the class's constructor method.
When Redux initializes it dispatches a "dummy" action to fill the state. So your counter reducer was called with state equal to undefined . This is exactly the case that "activates" the default argument. Therefore, state is now 0 as per the default state value ( state = 0 ).
As the first argument passed in to connect , mapStateToProps is used for selecting the part of the data from the store that the connected component needs. It's frequently referred to as just mapState for short. It is called every time the store state changes.
ownProps are the attributes that are passed when the component is used. In plain React these would be just called props.
The problem is your mapStateToProps
object, namely, you are expecting the flags to be on the rootstate
const mapStateToProps = (state) => {
return {
isLoginPending: state.isLoginPending,
isLoginSuccess: state.isLoginSuccess,
isloginError: state.isloginError
}
}
However, when we see your root reducer, you have a multilevel state that adds these flags inside the state.loginForm
const rootReducer = combineReducers({
loginForm: emailReducer
});
So changing your mapStateToProps like this should do
const mapStateToProps = (state) => {
return {
isLoginPending: state.loginForm.isLoginPending,
isLoginSuccess: state.loginForm.isLoginSuccess,
isloginError: state.loginForm.isloginError
}
}
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