Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-Redux: Combining reducers fails

Tags:

reactjs

redux

I have a React app built using Redux and Redux-Thunk. Everything works fine, until I try to combine reducers per the Redux docs.

Given an initial, functional reducer

export default function bigReducer(state = { events: [], flash: [] }, action) {
  switch (action.type) {
  case EVENTS_UPDATED:
    return _.extend({}, state, { events: action.pathway_events })
  case FLASH_MESSAGE_UPDATED:
    return _.extend({}, state, { flash: action.flash })
  default:
    return state
  }
}

When I try to create a composite reducer

function flashReducer(state = { flash: [] }, action) {
  switch (action.type) {
  case FLASH_MESSAGE_UPDATED:
    return _.extend({}, state, { flash: action.flash })
  default:
    return state
  }
}

function eventReducer(state = { events: [] }, action) {
  switch (action.type) {
  case EVENTS_UPDATED:
    return _.extend({}, state, { events: action.pathway_events })
  default:
    return state
  }
}

// either with simple reducer composition
export default function bigReducer(state = {}, action) {
  return {
    flashReducer: flashReducer(state.flash, action),
    eventReducer: eventReducer(state.events, action)
  } 
}

// or with the combineReducers function
export default const reducer = combineReducers({
  flashReducer,
  eventReducer
})

the initial state and the reducers seem to get mixed up

// logging the state
var EventListContainer = connect((state) => {
  console.log(state)
  return { events: state.events })(React.createClass({ ...

// returns the incorrect state
# => Object {flashReducer: Array[0], eventReducer: Array[17]}

How can I combine reducers using React and Redux?

like image 264
steel Avatar asked Nov 10 '15 18:11

steel


1 Answers

My understanding from the docs is that a named reducer is delegated to handle only that part of the state with the top-level key corresponding to the reducer name. So

const reducer = combineReducers({
  flashReducer,
  eventReducer
})

implies that you have state like

const state = {
  flashReducer: {...},
  eventReducer: {...}
}

So you need to a) name your reducers the same as the top-level keys they're supposed to manage, and b) have their default state only represent that subset of the full state object:

function flash(state = [], action) {
  switch (action.type) {
  case FLASH_MESSAGE_UPDATED:
    return action.flash.slice()
  default:
    return state
  }
}

function events(state = [], action) {
  switch (action.type) {
  case EVENTS_UPDATED:
    return action.pathway_events.slice()
  default:
    return state
  }
}

const reducer = combineReducers({
  flash,
  events
})
like image 57
nrabinowitz Avatar answered Oct 04 '22 21:10

nrabinowitz