0

guys. I've been learning redux and there is something about reducers that I haven't been able to fully comprehend.

In redux docs, a simple example is provided. In the reducers of said example, there is one reducer that calls another reducer. This is the code for these reducers:

function posts(state = {
  isFetching: false,
  didInvalidate: false,
  items: []
}, action) {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
      return Object.assign({}, state, {
        didInvalidate: true
      })
    case REQUEST_POSTS:
      return Object.assign({}, state, {
        isFetching: true,
        didInvalidate: false
      })
    case RECEIVE_POSTS:
      return Object.assign({}, state, {
        isFetching: false,
        didInvalidate: false,
        items: action.posts,
        lastUpdated: action.receivedAt
      })
    default:
      return state
  }
}

function postsBySubreddit(state = {}, action) {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
    case RECEIVE_POSTS:
    case REQUEST_POSTS:
      return Object.assign({}, state, {
        [action.subreddit]: posts(state[action.subreddit], action)
      })
    default:
      return state
  }
}

As you can see, postsBySubreddit calls posts. I understand this; it's reducer composition. What I don't understand is why the posts reducer is being called only in the REQUEST_POSTS case and not in the rest of them, yet it updates the state properly for the other cases. My flawed logic tells me that in order for the postsBySubreddit to work in all cases, it should employ the same mechanism in the RECEIVE_POSTS and the INVALIDATE_SUBREDDIT cases, as follows:

function postsBySubreddit(state = {}, action) {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
      return Object.assign({}, state, {
        [action.subreddit]: posts(state[action.subreddit], action)
      })
    case RECEIVE_POSTS:
      return Object.assign({}, state, {
        [action.subreddit]: posts(state[action.subreddit], action)
      })
    case REQUEST_POSTS:
      return Object.assign({}, state, {
        [action.subreddit]: posts(state[action.subreddit], action)
      })
    default:
      return state
  }
}

What am I missing? Thanks in advance. P.D. The full source code for this example can be found here.

h_tm
  • 137
  • 1
  • 9

1 Answers1

2

If you have multiple switch cases stacked on top of each other they will all run the bottom case's statements.

In this instance

case INVALIDATE_SUBREDDIT:
case RECEIVE_POSTS:
case REQUEST_POSTS:
  return Object.assign({}, state, {
    [action.subreddit]: posts(state[action.subreddit], action)
  })

is identical to

case INVALIDATE_SUBREDDIT:
  return Object.assign({}, state, {
    [action.subreddit]: posts(state[action.subreddit], action)
  })
case RECEIVE_POSTS:
  return Object.assign({}, state, {
    [action.subreddit]: posts(state[action.subreddit], action)
  })
case REQUEST_POSTS:
  return Object.assign({}, state, {
    [action.subreddit]: posts(state[action.subreddit], action)
  })
Mike
  • 1,442
  • 10
  • 20
  • Ok, great! Now I get it. Javascrpit's fall-through feature of the of the switch statement, right? [link]http://stackoverflow.com/questions/13207927/switch-statement-multiple-cases-in-javascript ? – h_tm Feb 06 '17 at 19:21
  • Yep, you got it – Mike Feb 07 '17 at 19:53