有没有办法在redux中重用reducer逻辑?

时间:2018-05-04 06:59:02

标签: reactjs redux reusability reducers

我正在使用react / redux构建我的应用程序。有多个按钮,应用程序需要跟踪是否单击这些按钮的状态。这些按钮都使用相同的reducer逻辑,即在单击按钮时将状态从true切换为false。唯一的区别是国家的名称。有没有办法通过定义"全局"来减少我的代码?可以应用于多个状态的减速器?请参阅此图片以获取example

谢谢!

2 个答案:

答案 0 :(得分:2)

我就是这样做的。而不是为每个按钮类型(例如MENU_BTNSEARCH_BTN等)分派唯一操作。我会调度{ type: 'TOGGLE_BUTTON', payload: 'menu' }并在减速器中

case TOGGLE_BUTTON:
  return {
    [payload]: !state[payload]
    ...state
  }

然后您可以像这样切换按钮

const toggleButton = key => ({
  type: 'TOGGLE_BUTTON',
  payload: key
})
dispatch(toggleButton('menu'))
dispatch(toggleButton('search'))

通过这种方式,您可以根据需要跟踪多个按钮。您的州将看起来像这样

...
buttons: {
  menu: true,
  search: false
}
...

您可以轻松地为每个按钮编写选择器

// Component displaying state of menu button //
let MyComponent = ({ menuButtonState }) => (
  <div>
  Menu button is {menuButtonState ? 'on' : 'off'}
  </div>
)
// Helper function for creating selectors //
const createGetIsButtonToggledSelector = key => state => !!state.buttons[key]
// Selector getting state of a menu button from store //
const getIsMenuButtonToggled = createGetIsButtonToggledSelector('menu')
// Connecting MyComponent to menu button state //
MyComponent = connect(state => ({
  menuButtonState: getIsMenuButtonToggled(state)
})(MyComponent)

答案 1 :(得分:0)

您可以创建一个通用高阶归约器,该接受器既接受给定的归约器功能,又接受名称或标识符。

function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

function createNamedWrapperReducer(reducerFunction, reducerName) {
  return (state, action) => {
    const { name } = action
    const isInitializationCall = state === undefined
    if (name !== reducerName && !isInitializationCall) return state

    return reducerFunction(state, action)
  }
}

const rootReducer = combineReducers({
  counterA: createNamedWrapperReducer(counter, 'A'),
  counterB: createNamedWrapperReducer(counter, 'B'),
  counterC: createNamedWrapperReducer(counter, 'C')
})

上面的 createdNamedWrapperReducer()方法应该可以直接使用。

有关更多详细说明或更多示例,请参见Redux's recipes for Reusing Reducer Logic