[lore-hook-redux] Update Redux store on background thread to prevent UI from temporarily freezing during large updates
Redux processes a single action at a time, meaning if an action creator dispatches 10 actions, they are processed in series, one at a time.
For small batches of actions, this seems fine, and the application remains responsive to user input. But if an action creator fires hundreds of actions, there's a noticeable "lockup" that occurs while Redux processes the actions.
Example
- User looks at a list of items with a "lore more" button at the bottom
- User presses the "load more" button
- API call is issues to fetch more items, let's say the next 10. But these items have data nested in them, let's say 20 resources per item in the list.
- When the data comes back and gets normalizes, these 10 items amount to 210 actions ((1+20)*10)
- While these actions are being processed by Redux, there's is a noticeable lack of responsiveness to the application. It may only last a second, but it's still a poor experience.
It should also be noted that it may only last a second in production, which the code is minified and uglified, but in development it's a much worse experience, and last noticeably longer (no metrics on actual difference, it's just definitely worse).
This happens because the application exists on a single thread, and if Redux is consuming the computational resources of that thread without breaking out of the loop, the application is unable to respond to user input (such as scrolling) until the loop is broken.
Possible Solutions
One way to solve this would be to put Redux on a background thread/worker, so updates to the store never affect the responsiveness of the application. I haven't done that before, so not sure exactly how it works. Would need to investigate. But registering a background workers seems to have possible UX issues related to developer experience...or at least there's a time in the past where I was seeing a console error that was being generated by a background worker that didn't exist, and I have to learn how to find them (service workers in Chrome?) and unregister it to remove the error. But I didn't create it - it was created by a demo app I downloaded and ran. So that was confusing.
Another way to solve this (that might be simpler) is to create a piece of middleware that "rations" how many actions the Redux store receives at any point in time. So if 210 actions were fired, this middleware would receive them all, and then only release 10 at a time to the Redux store, and force a break in the loop between each "segment" of data (i.e. wait for next tick).
Normally, that would cause React to update 21 times (because it updates every time the Redux store changes) but the debounceWait variable in the config for lore-hook-redux prevents Redux from notifying React until some tiny fraction of time has passed.
So using middleware, combined with debounceWait may be a valid solution that doesn't require using a background/service worker.