1
  • Action: fetch an array of data from the server.
  • Reducer: save an array of data to store.

My reducer saves the array of data in the expected immutable fashion:

return {
  ...state,
  arrayOfData: fetchedArrayOfData,
};

The fetch action happens periodically, but the content of the array remains the same most of the time. However, since a new reference is saved each time, the selector for this data will be considered "changed", and doesn't memoize well if used as an input for creatorSelector.

The only solution I can think of is to perform a deep-compare at the reducer, and if the contents are the same, simply return the original state:

return state;

If this common practice/pattern?

Note: I tried to look around, and most projects are doing the same thing that I was doing (i.e. return new state object), which will do not memoize well and causes selector transformations to run.

nima
  • 7,796
  • 12
  • 36
  • 53
Ryuu
  • 779
  • 11
  • 22
  • I do think that immutableJS can solve that by its nature. But I am not that sure as I am Angular dev – Akxe Oct 05 '21 at 13:49
  • 1
    Have you checked redux dev tools and see action payload really deliver desired new content? – Aloiso Gomes Oct 05 '21 at 15:15
  • @AloisoGomes, do you mean if the fetched data was correct? The fetched data is correct and is expected to be the same as previous fetch most of the time -- it only changes occasionally. – Ryuu Oct 06 '21 at 07:12

1 Answers1

1

There are some solutions like using immutableJS as mentioned in the comments but you can return your state conditionally by comparing your fetchedArrayOfData with the last one (which is stored in your state).

Assume there is a comparison function that gives two arrays and compares them.

In the reducer:

const previousFetchedData = state.fetchedArrayOfData;
const newFetchedData = action.payload.fetchedArrayOfData;

const resultOfComparision = isSameArray(previousFetchedData, newFetchedData) // true or false

if (resultOfComparision) { // case of same arrays
  return state
} else { // case of different arrays
  ...state,
  arrayOfData: fetchedArrayOfData,
};

Note 1: you can create your own comparison function but there are many nice ones in this post of StackOverflow which you can use them.

Note 2: using immutableJs and conditional returning data from reducer is common(in such scenario) and don't worry about using them.

Note 3: You can also compare your data at the component level by using the traditional way with shouldComponentUpdate.

Node 4: using middlewares like redux-saga will be useful, you can also implement the isSameArray function in the saga and then dispatch the proper action. read more on saga documentation.

Note 5: The best solution (in my thought) is to handle this case on the backend services with 304 status which means Not modified. then you can easily determine the right action according to the response status. more info on MDN documentation.

nima
  • 7,796
  • 12
  • 36
  • 53
  • 1
    On Note 2: Ah, i didn't realize `immutableJs` actually returns the same `state` reference if there are no changes, so it is essentially doing a comparison each time. I thought it will always return a new `state` reference. The pattern was masked away when I peeked at other projects. Thanks! – Ryuu Oct 06 '21 at 07:20