Skip to content

how to compose redux reducers with the same actions? #897

Closed
@ccorcos

Description

@ccorcos

I'm just getting started with redux and it looks amazing, but I'm a little worried about abstraction.

Suppose I have a really simple input component

inputReducer = function(state='', action) {
  if (action.type === 'ON_CHANGE') {
    return action.value
  }
  return state
}

inputOnChangeAction = function(e) {
  return {
    type: 'ON_CHANGE',
    value: e.target.value
  }
}

Now its trivial to hook this up to a component with an input.

reducer = combineReducer({
  username: inputReducer
})

But what happens when I have more than one input?

reducer = combineReducer({
  username: inputReducer
  password: inputReducer
})

Ok, I suppose we could change the action type to specify which input its referring too.

inputReducer = name => (state='', action) => {
  if (action.type === 'ON_CHANGE_'+name.toUpperCase()) {
    return action.value
  }
  return state
}

inputOnChangeAction = name => (e) => {
  return {
    type: 'ON_CHANGE_'+name.toUpperCase(),
    value: e.target.value
  }
}

reducer = combineReducer({
  username: inputReducer('username')
  password: inputReducer('password')
})

But now suppose I place two of the same views side-by-side? Now I need to modify the action yet again to specify which input in which view I'm referring to.

inputReducer = index => name => (state='', action) => {
  if (action.type === 'ON_CHANGE_'+name.toUpperCase()+'['+index+']') {
    return action.value
  }
  return state
}

inputOnChangeAction = index => name => (e) => {
  return {
    type: 'ON_CHANGE_'+name.toUpperCase()+'['+index+']',
    value: e.target.value
  }
}

reducer = function(state:[{username:'', password:''},{username:'', password:''}], action) {
  return state.map({username, password}, index) => {
    return {
      username: inputReducer(index)('username')(username)
      password: inputReducer(index)('password')(password)
    }
  }
}

Oy vey. Whats tough about this is that the input reducer somehow needs to know about how the rest of the app is structured. That just doesnt seem right. Ideally we would be able to abstract out the input's actions and reducers based on how the parent decides to arrange them. I suppose we could do this with a high-order function. But this is all getting pretty tedious. Am i missing something? How are you dealing with this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions