假设我有这个状态结构中的终极版店:如何使用`reselect`来记忆数组?
{
items: {
"id1" : {
foo: "foo1",
bar: "bar1"
},
"id2": {
foo: "foo2",
bar: "bar2"
}
}
}
此店由接收物品焕发出新的价值观的演变:
const reduceItems = function(items = {}, action) {
if (action.type === 'RECEIVE_ITEM') {
return {
...items,
[action.payload.id]: action.payload,
};
}
return items;
};
我想显示呈现列表的根视图SubItem视图,只提取一部分状态。 例如子项目视图只关心FOOS,并且应该得到它:
function SubItem({ id, foo }) {
return <div key={id}>{foo}</div>
}
因为我只关心美国的“分部”,这就是我想通过一个“哑”根观点是什么:
const Root = function({ subitems }) {
// subitems[0] => { id: 'id1', foo: "foo1" }
// subitems[1] => { id; 'id2', foo : "foo2" }
const children = subitems.map(SubItem);
return <div>{children}</div>;
};
我可以轻松地连接该组件订阅的状态变化:
function mapStatesToProps(state) {
return {
subitems: xxxSelectSubItems(state)
}
}
return connect(mapStatesToProps)(Root)
我的根本问题是,当发生什么I D状态的一部分不关心(bar
)的变化。 甚至,当我收到一个项目,那里既没有foo
也不bar
已经改变的新值:
setInterval(() => {
store.dispatch({
type: 'RECEIVE_ITEM',
payload: {
id: 'id1',
foo: 'foo1',
bar: 'bar1',
},
});
}, 1000);
如果我用“天真”选择执行:
// naive version
function toSubItem(id, item) {
const foo = item.foo;
return { id, foo };
}
function dumbSelectSubItems(state) {
const ids = Object.keys(state.items);
return ids.map(id => {
const item = state.items[id];
return toSubItem(id, item);
});
}
然后列表每个被调用的对象都是一个全新的对象,而且我的组件每次都会呈现,无所事事。
当然,如果我使用“常量”选择,总是返回相同的列表中,因为所连接的组件是纯粹的,它是重新呈示(不过这只是为了说明连接组件是纯):
// fully pure implementation
const SUBITEMS = [
{
id: 'id0',
foo: 'foo0',
},
];
function constSelectSubItems(state) {
return SUBITEMS;
}
如果我使用列表更改但包含相同元素的“almostConst”版本,现在这会变得有点棘手。
const SUBITEM = {
id: 'id0',
foo: 'foo0',
};
function almostConstSelectSubItems(state) {
return [SUBITEM];
}
现在,可以预见,由于列表不同,即使里面的项目是相同的,组件每秒都会被重新渲染。
这是我虽然'重新选择'可以帮助,但我想知道如果我没有完全忽略这一点。我能得到reselect
以此来表现:
const reselectSelectIds = (state, props) => Object.keys(state.items);
const reselectSelectItems = (state, props) => state.items;
const reselectSelectSubItems = createSelector([reSelectIds, reSelectItems], (ids, items) => {
return ids.map(id => toSubItem(id, items));
});
但后来它的行为完全一样的幼稚版本。
所以:
- 是毫无意义,试图memoize的阵列?
- 可以重新选择处理这个吗?
- 我应该改变国家的组织吗?
- 我应该只使用“deepEqual”测试在Root上实现shouldComponentUpdate?
- 我应该放弃Root作为一个连接组件,并且让每个LeafItems都是连接组件吗?
- 可以immutable.js帮忙吗?
- 是不是不是问题,因为React很聪明,一旦虚拟dom被计算出来就不会重新绘制任何东西。
这是可能的,我试图做他毫无意义,并在我的REDEX存储隐藏一个问题,所以随时陈述明显的错误。