Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use reselect on a changing list, when the objects are the same?

I use reselect to get parts of my redux state. i have a list of objects in my state. One of my subselector for my create selector is a filter function of this list:

state => state.list.filter(filterFunction)

So i pass this to my createSelector:

createSelector(
  state => state.list.filter(filterFunction),
  (subsetOfObjects) => subsetOfObjects.map(doSomething)
);

This filter function returns a subset of my objects in the list. So if the list changes, reselect always returns a new object, even if the subset didn't changed, because the list isn't the same (fully correct).

is there a possibility to get only a new object if there are changes to the objects or the filtered list?

like image 286
bitrevolution Avatar asked Jun 20 '16 08:06

bitrevolution


People also ask

What is reselect and how it works?

Reselect provides a function called createSelector to generate memoized selectors. createSelector accepts one or more "input selector" functions, plus an "output selector" function, and returns a new selector function for you to use.

Why we use reselect in Redux?

A library for creating memoized "selector" functions. Commonly used with Redux, but usable with any plain JS immutable data as well. Selectors can compute derived data, allowing Redux to store the minimal possible state.

How do selectors work?

A selector is a function that accepts Redux state as an argument and returns data that is derived from that state. Selectors can provide performance optimizations to your application and can also help you encapsulate your global state tree.


Video Answer


1 Answers

After all i had an idea which could work:

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(
  state => state.order,
  order => createSelector(
    ...order.map(id => state => state.list[id]),
    selector,
  )
);

The line ...order.map(id => state => state.list[id]), will spread the objects as arguments. They will be the same if the order-array will not be changed. So i can generate a new Object with only the Objects listed in the order.

The evaluation function of the first create Selector only gets called if the order array changes. If this happens, a recalculation of the result is necessary anyway. So this is fine. The second one only recalculates if it gets new values. The values are functions that are generated out of the order array. Even if the list object changes (due to more entries or smaller changes on other objects that are not considered in the current list), the pointer to the objects of the order array stays the same. So we always get a the same objects as arguments to our second evaluation function. This prevents an unwanted update.

like image 167
bitrevolution Avatar answered Sep 30 '22 08:09

bitrevolution