2016-06-20 13 views
5

私は私の還元状態の部品を得るために再選択を使用します。私は私の状態のオブジェクトのリストを持っています。私のセレクタを作成するための私のsubselectorの一つは、このリストのフィルタ機能である:オブジェクトが同じ場合、変更リストでreselectを使用するにはどうすればよいですか?

state => state.list.filter(filterFunction) 

は、だから、私はcreateSelectorにこれを渡します

このフィルタ機能はリストに私のオブジェクトのサブセットを返します。 。したがってリストが変更された場合、リストは同じではない(完全に正しい)ため、サブセットが変更されていなくても、常に新しいオブジェクトが返されます。

オブジェクトまたはフィルタリングされたリストに変更がある場合、新しいオブジェクトのみを取得する可能性はありますか?

+0

これは、 'filter'(入力セレクタ)が常に新しいオブジェクトを返すために起こります。 AFAIK、 'reselect'は入力セレクタの結果を' === '(' state.list.filter(filterFunction)=== state.list.filter(filterFunction) ')と比較します。リストは変更されません。 –

+0

あなたがそれを実装した方法を明確にするために、 'createSelector'は役に立たなくなってしまいます。入力セレクタ(フィルタ)は常に新しいオブジェクトを返すため、状態が変化しなくてもすべての呼び出しで再計算されます。 –

答えて

3

私は仕事ができるという考えを持っていたすべての後:

const list = { 


object1: { 
    id: 'object1', 
    }, 
    object2: { 
    id: 'object2', 
    }, 
    object3: { 
    id: 'object3', 
    }, 
}; 

const order = ['object1', 'object3']; 

const selector = (...args) => args.reduce((prev, curr) => ({...prev, [curr.id]: curr}), {}); 

createSelector(
    ...order.map(id => list[id]), 
    selector, 
); 

ライン...order.map(id => list[id]),は、引数としてオブジェクトを分散します。オーダーアレイが変更されない場合も同じです。だから私は順序で記載されているオブジェクトだけで新しいオブジェクトを生成することができます。

0

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一部を作っているが、それは奇妙かもしれません。

関連する問題