In Redux is it better for performance to add a property to the items in the store or to calculate it in the container?

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/409417

  •  10-03-2021
  •  | 
  •  

Question

I'm writing my first Redux app. In my store, I have ~300-500 Island objects that I retriev from an API and index by an id string in an object (being treated like a map). When I'm editing one of these Islands by setting editId in the store, the buttons for the other Islands need to be disabled. I can think of three ways I can do this.

  1. Have all of the components watch editId for changes and check their Island.id against the editId (I'm guessing this is very slow)
  2. Add a disabled prop to my island component, have the container that maps the Islands to components watch for editId, and calculate disabled for each island on render
  3. Add a disabled field to the Island objects in the store and update each of these objects when my edit action

My hunch is option 2, as that would definitely be the cleanest approach.

This question is coming from a place of migrating from mobx (which had terrible performance) to redux, and hoping performance improves. If any of the three of these will have virtually the same performance, then I'll choose option 2. I just don't know if there's a redux pattern established that I should be using.

Was it helpful?

Solution

Making some likely assumptions...

500 objects is not a lot. Calculating a bool on 500 objects is an intrinsically tiny operation.

Your cost is unlikely in the derivation of the boolean prop from your objects.

A common experience is excess expense in the rendering process for those objects. In Redux make sure your changes occur as a single state update in a reducer and not via multiple actions for each object from causing multiple computations of state. If you need to use multiple actions to achieve your goal look into using https://react-redux.js.org/api/batch.

If you are using a single action and there is a single run of all the reducers for these changes then the issue can commonly be in the computation of the state itself. In this case it is likely you are recreating the full object graph for these 500 objects in the store every pass because you are modifying a property of each of those 500 objects. The root object must also be replaced with updated references to those 500 objects.

This in itself is not expensive, but can have expensive rendering implications. As all the references here change it is implied with no optimization that there will be 500 rerenders of components, and depending on how you handle the parent object 500 remounts.

If your island objects correlate to a sizable render it's quickly possible to run into performance issues.

The first link below offers a tool for some insights. The second link is some explanation of handling shouldComponentUpdate. https://github.com/welldone-software/why-did-you-render https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action

I believe your primary goal in all of this should be ensuring that the disabled prop change is only triggering a change once for the disabled prop in the dom. If you still have issues, compare how doing a "fast" vanilla JS "disabled" attribute update of 500 disabled island elements goes. If it is comparable it may just be the cost of doing business with 500 objects that cause renders. If not there is more to understand.

Licensed under: CC-BY-SA with attribution
scroll top