EDIT
私は眠っこの場合のために、単純な(多分、まだ不要)溶液を用いて(笑真剣)夢見ていました。フィルタ結果にプリミティブ型を返さなければならないので、JSON.stringify()
itとJSON.parse()
を2番目のセレクタで返すことができます。以下のテストスイートは渡し:
const state = {
list: [
{ id: 1, active: true },
{ id: 2, active: false },
{ id: 3, active: false },
{ id: 4, active: false }
]
}
const getFilteredListIds = createSelector(
(state) => JSON.stringify(state.list.filter((object) => !!object.active)),
(filteredList) => JSON.parse(filteredList).map((object) => object.id)
)
expect(getFilteredListIds.recomputations()).toEqual(0)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
const newState = {
list: [
...state.list,
{ id: 5, active: false } // should not change subset
]
}
expect(getFilteredListIds(newState)).toEqual([1]) // subset didn't change
expect(getFilteredListIds.recomputations()).toEqual(1) // pass :)
しかし、あなたのユースケースに応じて、それはすべての呼び出しに対してフィルタよりも遅くなることがあります。そのパフォーマンスをテストする場合は、私たちと共有してください。
FIRST POST
私がcommentsに言ったように、createSelector
は無用になりますが、実装しました方法。
const state = {
list: [
{ id: 1, active: true },
{ id: 2, active: false },
{ id: 3, active: false },
{ id: 4, active: false }
]
}
const getFilteredListIds = createSelector(
(state) => state.list.filter((object) => !!object.active),
(filteredList) => filteredList.map((object) => object.id)
)
expect(getFilteredListIds.recomputations()).toEqual(0)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1) // fail
まず、この最初の問題を解決するためにいくつかの修正を行いました。
const state = {
list: [
{ id: 1, active: true },
{ id: 2, active: false },
{ id: 3, active: false },
{ id: 4, active: false }
]
}
const getList = (state) => state.list
// it makes filter only happen if state.list changes
const getFilteredList = createSelector(
getList,
(list) => list.filter((object) => !!object.active)
)
const getFilteredListIds = createSelector(
getFilteredList,
(filteredList) => filteredList.map((object) => object.id)
)
expect(getFilteredListIds.recomputations()).toEqual(0)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
// everything pass
今、あなたの質問は有効です。
は、オブジェクトへの変更またはフィルタされたリストがある場合にのみ、新しいオブジェクトを取得する可能性はありますか?
これは正しいですか?
const newState = {
list: [
...state.list,
{ id: 5, active: false } // should not change subset
]
}
expect(getFilteredListIds(newState)).toEqual([1]) // subset didn't change
expect(getFilteredListIds.recomputations()).toEqual(1) // fail
しかし、最後の行は失敗しますrecomputations()
は2
になるので、これを解決するための私が見る唯一の方法は、あなたの状態のメモ化filteredList
一部を作っているが、それは奇妙かもしれません。
これは、 'filter'(入力セレクタ)が常に新しいオブジェクトを返すために起こります。 AFAIK、 'reselect'は入力セレクタの結果を' === '(' state.list.filter(filterFunction)=== state.list.filter(filterFunction) ')と比較します。リストは変更されません。 –
あなたがそれを実装した方法を明確にするために、 'createSelector'は役に立たなくなってしまいます。入力セレクタ(フィルタ)は常に新しいオブジェクトを返すため、状態が変化しなくてもすべての呼び出しで再計算されます。 –