我正在重构一个React / Redux应用程序,该应用程序已构建到需要去重化许多reducer逻辑的地步。我已经研究了High Order Reducers,但我很难把头放在如何使它们为我服务上。
这是一个例子:
reducers.js
import components from './entities/components';
import events from './entities/events';
import items from './entities/items';
const entities = combineReducers({
components,
items,
events,
});
我正在使用normalizr。这是我的状态的一个想法。对于此示例,只知道事件可以属于组件或项目,但是在其他方面两者是可区分的。
{
entities: {
components: {
component_1: {
events: ['event_1'],
},
},
items: {
item_1: {
events: ['event_2'],
},
},
events: {
event_1: {
comment: "foo"
},
event_2: {
comment: "bar"
}
}
}
}
我在所有3个reducer中都使用了
EVENT_ADD
操作类型。 component.js 和 item.js (在下面)的逻辑是相同的,但是两者还具有针对其类型的独立操作。在这里,我通过使用Immutable.js的
.has()
函数检查目标ID是否在该状态的一部分中,从而不必要地将事件添加到了错误的位置。export default (state = getInitState('component'), action) => {
switch (action.type) {
case EVENT_ADD:
return state.has(action.targetId) ?
state.updateIn(
[action.targetId, 'events'],
arr => arr.push(action.event.id)
) :
state;
[...]
}
}
在 event.js 中,我也在这里使用
EVENT_ADD
将事件的内容添加到该状态的该部分。export default (state = getInitState('events'), action) => {
switch (action.type) {
case EVENT_ADD:
return state.set(action.event.id, fromJS(action.event));
[...]
}
}
我对高阶 reducer 的理解是,我需要执行以下一项或两项操作:
ADD_EVENT_${entity}
(因此使我同时使用 event.js 中的EVENT_ADD_COMPONENT
和EVENT_ADD_ITEM
来创建事件,而不管其父级如何。)似乎我想要一些 sharedReducer.js ,可以在组件和项之间共享逻辑以执行
ADD_EVENT
,DELETE_EVET
等操作,然后每个实体还具有两个独立的reducer。我不确定如何才能做到这一点,或者不确定哪种设计模式是最好的。任何指导将不胜感激。谢谢!
最佳答案
短语“高阶$ THING”通常表示“以$ THING作为参数,并且/或者返回新的$ THING的函数”(其中“$ THING”通常是“function”,“component”,“reducer” ”等)。因此,“高阶缩减器”是一个接受一些参数并返回缩减器的函数。
在您链接的Structuring Reducers - Reusing Reducer Logic部分中,最常见的高阶化简器示例是一个函数,该函数接受某种区分值,例如ID或操作类型或子字符串,并返回一个新的化简器函数,该函数使用该区分值来了解其实际值。应该回应。这样,您可以创建同一功能的多个实例,即使其余逻辑相同,也只有“正确的”一个实例才能响应给定的操作。
看来您通常已经走在正确的轨道上,并且有几种方法可以组织共享逻辑。
一种方法可能是先明确查找“常见”操作并运行该reducer,然后查找特定情况:
export default (state = getInitState('events'), action) => {
// First check for common cases
switch(action.type) {
case EVENT_ADD:
case OTHER_COMMON_ACTION: {
state = sharedReducer(state, action);
break;
}
}
switch(action.type) {
case EVENT_ADD:
case EVENTS_SPECIFIC_ACTION: {
return eventsSpecificReducer(state, action);
}
}
return state;
}
另一种方法可能是使用类似
reduce-reducers
实用程序的工具,如Structuring Reducers - Beyond combineReducers
部分所示:const entities = combineReducers({
components : reduceReducers(componentsReducer, sharedReducer),
items : reduceReducers(itemsReducer, sharedReducer)
events,
});
希望这能为您指明正确的方向。如果您还有其他问题,请随时在这里提问,或在Discord的Reactiflux聊天 channel 中-邀请链接位于https://www.reactiflux.com。 (注意:我是Redux的维护者,"Structuring Reducers" docs section的作者,并且是Reactiflux的管理员。)