有没有办法在 redux 中重用 reducer 逻辑?
Is there a way to reuse a reducer logic in redux?
我正在使用 react/redux 构建我的应用程序。有多个按钮,应用程序需要跟踪这些按钮是否被单击的状态。这些按钮都使用相同的 reducer 逻辑,即在单击按钮时将状态从 true 切换为 false。唯一的区别是州的名称。有没有办法通过定义一个可以应用于多个状态的“全局”reducer 来减少我的代码?请参考此图片以获得 example
谢谢!
这就是我要做的。而不是为每个按钮类型(如 MENU_BTN
、SEARCH_BTN
等)调度独特的操作。我会调度 { type: 'TOGGLE_BUTTON', payload: 'menu' }
并在 reducer
中
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)
您可以创建一个通用高阶 reducer,它接受给定的 reducer 函数和名称或标识符。
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。
我正在使用 react/redux 构建我的应用程序。有多个按钮,应用程序需要跟踪这些按钮是否被单击的状态。这些按钮都使用相同的 reducer 逻辑,即在单击按钮时将状态从 true 切换为 false。唯一的区别是州的名称。有没有办法通过定义一个可以应用于多个状态的“全局”reducer 来减少我的代码?请参考此图片以获得 example
谢谢!
这就是我要做的。而不是为每个按钮类型(如 MENU_BTN
、SEARCH_BTN
等)调度独特的操作。我会调度 { type: 'TOGGLE_BUTTON', payload: 'menu' }
并在 reducer
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)
您可以创建一个通用高阶 reducer,它接受给定的 reducer 函数和名称或标识符。
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。