1

I have two models, where model A references items in model B. When I delete items from model B, react rerenders before I can update model A to also delete the referenced items.

Example:

I have a feed. The feed is made up of different types of items. Each type of item is stored in its respective model. The feed order is stored as an array of item IDs, referencing the items in their different substores.

I have made a minimal failing example here. The issue occurs after clicking the button three times

https://codesandbox.io/s/deleting-referenced-items-kmw1e

The key line is

else console.error(">>>> feed order contains deleted item", id);

It's problematic that the feed order might contain deleted items because it could mean there is a programming error that resulted in bad references. In this case it's not a programming error, the second store just hasn't updated yet.

Is there a way I might be able to batch the createAndDeleteTodo, to not evaluate all listeners until the entire thunk and all subthunks have completed?

In the above example it's trivial enough to just have one master action which updates the feed order and the items but it would feel cumbersome if there was more than just one type of item as each item type lives in it's own respective model.

david_adler
  • 9,690
  • 6
  • 57
  • 97
  • I thinking that derived state / a computed variable might be a better way of handling this edge case but it gives less control over updating the array. – david_adler Apr 14 '21 at 07:52

2 Answers2

1

The same thunk action is triggering multiple Actions. And as per the definition of useStoreState:

The useStoreState will execute any time an update to your store's state occurs

So, in effect, when you do this inside the thunk:

  actions.setTodos({ newTodos: [newTodo], todoToDelete });
  actions.updateFeedOrder({ newTodos: [newTodo], todoToDelete });

there are two actions being dispatched and those would account for a separate store state change event listener. You will get multiple render calls for the multiple store updates.

You have two options:

Nagaraj Tantri
  • 5,172
  • 12
  • 54
  • 78
  • Option1 (mentioned in problem statement) and option 2 both seem quite cumbersome. It's trivial with one type in the array but if you have many models each coming together in this feed it becomes messy. Also note from your codesandbox - don't modify state in a thunk "whilst you are able to access the store's state via this API your thunk should not perform any mutation of this state" – david_adler Apr 14 '21 at 07:51
  • @david_adler While Thunk is not needed to modify the state, the analogy is to keep things together in one action which updates the store. The way this can only be handled is by either making one store update OR only allow a re-render if the required store is at a given state. As the best practice, for a given component, keep one store object as a source of truth and make sure it only renders if that store value is updated. This means creating a nested object for that view component and update it in one go. Chain multiple API call's and update that in one action. – Nagaraj Tantri Apr 14 '21 at 08:44
0

It seems the problem is that you're dispatching to redux store 2 times. First when you create new items and then when you delete them.

I'd suggest to do it this way:

  1. Create a deep copy of object/array you wanna work with.
  2. Make both operations on that copy.
  3. Dispatch that value to the store.

This way nothing will be rerendered until both operations are finished.

Serhiy Mamedov
  • 1,080
  • 5
  • 11