PeternDev
PeternDev

Reputation: 89

Redux state props value is undefined

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;

Upvotes: 6

Views: 6112

Answers (2)

Sagiv b.g
Sagiv b.g

Reputation: 31024

You are passing loginForm as a store to the connected components via your rootReducer:

const rootReducer = combineReducers({
  loginForm: emailReducer
});  

So inside mapstateToProps you could do:

const mapStateToProps = (state) => {
    return {
       isLoginPending: state.loginForm.isLoginPending,
       isLoginSuccess: state.loginForm.isLoginSuccess,
       isloginError: state.loginForm.isloginError
    }
}

Upvotes: 0

Icepickle
Icepickle

Reputation: 12796

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
    }
}

Upvotes: 11

Related Questions