8

I'm updating a set of entities using a HTTP Patch request to a remote backend. The response from the backend includes the updated entities only (i.e., not all entities).

I set up my reducer with an entity state adapter and use updateMany to update my entities:

case settings.SettingsActionTypes.UpdateSettingsSuccess: {
   return {
     ...state,
     ...adapter.updateMany(action.payload.map((category) => Object.assign({}, {id: category.name, changes: category})), state),
     loaded: true,
     loading: false,
   }
 }

While this updates the entities that received an update, it deletes all others that are not returned by the backend.

Is there a way to tell ngrx to only update entities that are included in the action.payload?

tilo
  • 14,009
  • 6
  • 68
  • 85
  • 1
    Have you tried to remove `...state` ? because `...adapter.updateMany` already returns the state. Might be the problem. – Okan Aslankan Jan 14 '18 at 22:19
  • @OkanAslankan Thanks for your comment. I tried that without success. – tilo Jan 15 '18 at 08:19
  • I've had similar problem at work recently. As we use ImmutableJS implementation for our state I've achieved what you looking for using a custom callback, checking for `undefined`/empty values, of [mergeDeepWith](https://github.com/facebook/immutable-js/blob/master/src/methods/mergeDeep.js) of the Record data structure implementation. Will provide example as answer if you won't be able to achieve it tomorrow. – Shahar Galukman Jan 15 '18 at 20:07
  • Reduces are pure function..So, as per my understanding actions like `updateMany` should not be here, Reducer should get updated record only in payload for this kind of stuff you should use Effects, otherwise you code look absolutely great.... It should work fine if you try it with some hard-coded values. – Ashwani Kumar Jan 18 '18 at 07:53

1 Answers1

5

You shouldn't spread so many times.

Update many takes the state as a parameter you can use your spread fu in there.

return adapter.updateMany( 
   action.payload.map((category) => Object.assign({}, {id: category.name, changes: category})), 
   { ...state, loaded: true, loading: false }
);
MTJ
  • 1,059
  • 1
  • 10
  • 23
  • Actually this didn't solve the issue of removed items, but that was my fault (while dispatching the update action, I altered the state). Nevertheless, you brought me on track pointing out the other issue. Thanks – tilo Jan 25 '18 at 07:12