Nyxynyx
Nyxynyx

Reputation: 63599

Understanding Redux's Reducer storing State

While trying to understand the react/redux code in gillisd/react-router-v4-redux-auth, I am confused about the state state.auth.authenticated returned by mapStateToProps.

For example, in the event where a user logins using the form,

/client/src/components/auth/signin.js

class Signin extends Component {

    handleSubmit({email, password}) {
        this.props.signinUser({email, password});
    }

submitting the form causes the signinUser function to dispatch an action with type: AUTH_USER

/client/src/actions/index.js

export function signinUser({email, password}) {

  return function (dispatch) {

    // submit email and password to server
    const request = axios.post(`${ROOT_URL}/signin`, {email, password})
    request
      .then(response => {

        // -if request is good, we need to update state to indicate user is authenticated
        dispatch({type: AUTH_USER})

which triggers the reducer to update the state

/client/src/reducers/auth_reducer.js

export default function authReducer(state = {}, action) {
    switch (action.type){
        case AUTH_USER:
            return {...state, error: '', authenticated: true};

Question: Why does {...state, error: '', authenticated: true} updates state.auth.authenticated to true instead of updating state.authenticated to true?

I am guessing state.auth.authenticated was updated to true because the code below accesses it via state.auth.authenticated. Why is this?

/client/src/components/auth/signin.js

function mapStateToProps(state) {
  return {
    authenticated: state.auth.authenticated,
    errorMessage: state.auth.error
  }
}

Upvotes: 1

Views: 225

Answers (2)

Andrew Li
Andrew Li

Reputation: 57934

Because of combineReducers in index.js.

When you call combineReducers, you combine all your reducers into single one used to construct the store. But every single individual reducer you pass to combineReducers governs only its slice of state. Thus, since you're passing authReducer under the key:

auth: authReducer

The first argument passed to authReducer is state.auth. The authReducer essentially only governs the auth key of state -- its slice of state. So when the authReducer returns the new state, it updates its slice, state.auth, not just state itself. So state.auth.authenticated is changed, not state.authenticated. This is mentioned in the documentation:

The state produced by combineReducers() namespaces the states of each reducer under their keys as passed to combineReducers()

Similarly, the redux-form reducer will only ever modify state.form because it governs on the state.form slice of state as per its key.

Upvotes: 2

Mohit Mutha
Mohit Mutha

Reputation: 3001

Inside the combineReducers in index.js the authReducer has been named auth hence the state is accessible as state.auth.XXX

Have a look at https://github.com/gillisd/react-router-v4-redux-auth/blob/master/client/src/reducers/index.js

Upvotes: 1

Related Questions