我正在开发一个React / Redux应用程序,该应用程序允许将“小部件”添加到页面并在2D空间中进行操作。要求可以一次选择和操作多个小部件。我当前状态树的简化版本如下所示…
{ widgets: { widget_1: { x: 100, y: 200 }, widget_2: { x: 300, y: 400 }, widget_3: { x: 500, y: 600 } }, selection: { widgets: [ "widget_1", "widget_3" ] } }
我目前有这棵树由2个reducer管理,一个管理widgets状态,另一个管理selection状态。选择状态减少器可以简化为(注意:我也使用Immutable.js)…
widgets
selection
currentlySelectedWidgets(state = EMPTY_SELECTION, action) { switch (action.type) { case SET_SELECTION: return state.set('widgets' , List(action.ids)); default: return state } }
这一切似乎都工作得很好,但我现在有一个要求,我正在努力适应这个模型…
为了实现UI,我需要使当前选择具有x / y属性,该属性反映了当前选定的小部件x / y坐标的左上角。一个示例状态可能看起来像…
{ widgets: { widget_1: { x: 100, y: 200 }, widget_2: { x: 300, y: 400 }, widget_3: { x: 500, y: 600 } }, selection: { x: 100, y: 200, widgets: [ "widget_1", "widget_3" ] } }
这里的逻辑相当简单,例如,找到min()所有选定的小部件x和y值,但是我不确定如何根据化简器组成来处理此问题,因为化简currentlySelectedWidgets器无法访问widgets状态树的一部分。我考虑过…
min()
x
y
currentlySelectedWidgets
combineReducers()
currentlySelectedWidgets()
我热衷于听到关于其他人如何处理类似情况的其他建议,似乎管理“当前选择”必须是其他人必须解决的普遍状态问题。
这是Reselect的好用例:
创建一个选择器以访问您的状态并返回 派生 数据。
举个例子:
import { createSelector } from 'reselect' const widgetsSelector = state => state.widgets; const selectedWidgetsSelector = state => state.selection.widgets; function minCoordinateSelector(widgets, selected) { const x_list = selected.map((widget) => { return widgets[widget].x; }); const y_list = selected.map((widget) => { return widgets[widget].y; }); return { x: Math.min(...x_list), y: Math.min(...y_list) }; } const coordinateSelector = createSelector( widgetsSelector, selectedWidgetsSelector, (widgets, selected) => { return minCoordinateSelector(widgets, selected); } );
在coordinateSelector现在可以访问你的分x和y性质。上面的选择器仅在widgetsSelector或selectedWidgetsSelector状态更改时才会更新,这是一种非常有效的方式来访问您想要的属性,并避免在状态树中重复。
coordinateSelector
widgetsSelector
selectedWidgetsSelector