假設我有這個狀態結構中的終極版店:如何使用`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存儲隱藏一個問題,所以隨時陳述明顯的錯誤。