Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
feat(query): support for batching of UI updates as the result of a database "array" loading #212
What is the current behavior?
I have a collection in my database, similar to this:
In my UI, I have a parent container element, and inside of it, boxes for each of the children. I use
However, the parent element requests/accesses/checks the data of all the children. This causes all of the children data to be requested from Firebase (however, as individual items rather than just the collection in one go, for technical reasons). It then gets sent to the app, and react-redux-firebase places it into the store. So far so good.
However, we get performance issues when we have many items, because react-redux-firebase downloads and places the items into the store one by one -- from what I can tell in the profiler. This means that the parent container element gets rendered many times during the loading/storing of the item data.
At first glance it seems like the solution is to have the parent element request all the child data in one go. However, I'm using a deep, function-tree-based data-retrieval system, so switching to "in one go" requesting would remove a lot of convenience benefits that currently exist.
Another thought is to use a library like https://github.com/tappleby/redux-batched-subscribe. However, I tried, and it doesn't reduce the update count significantly. I'm pretty sure it's because it only batches UI updates for a given database entry being added to the store -- and in my case, this base number of data entries/requests is itself too high.
What I'm suggesting is a feature by which react-redux-firebase tracks how often certain components (probably marked using an opt-in decorator) get re-rendered based on react-redux-firebase store updates, and if it sees that a component has been rendering very frequently for a sequence of add-entry-to-store actions, it could "suspend rerendering" for that component until the sequence of actions is complete.
It might be difficult to implement, so I understand it might not actually ever get implemented. But I figured I would bring it up in case it seems of use to other developers.
(it becomes a pretty big problem in larger apps, where there are hundreds of redux-connected components on-screen at once, and they all have the potential to react to common-data changes in the database part of the store -- combined with the common-data changing hundreds of times all at once because of a batch of entries being received at basically the same time but entered sequentially)
@Venryx Thanks for the suggestion! Performance of single views with tons of data updates has been something we have been noticing and starting to look into at work (we use this in production for our platform). After we do a more thorough investigation, I will better be able to determine a feature/bugfix and its associated timeline.
Really like the idea of another HOC to help track and maybe even control this, so that will be kept in mind.
Got a quick solution working:
You also have to add a special handler to your root reducer, so it will take the "ApplyActionSet" action, take out the actions in the inner array, and apply each one sequentially.
In my project, this looks like:
Its performance impact on my project is quite large. Loading a tree of ~200 nodes went down from 60 seconds to 11!
Inspecting the actions dispatched in dev-tools shows that it's now batching some sets of over 200 START/SET actions into just one -- keeping the components that depend on multiple entries in that data from having to continually rerender.