React 16.7.0 was released a day ago and there are a couple of good and bad things in this release.
– A fix for a bad performance issue of
React.lazy. This defect was affecting only apps with large numbers of lazily-loaded components.
Previously, React would attach a new listener every time a promise is thrown, regardless of whether the same listener was already attached during a previous render. Because React attempts to render every time a promise resolves, the number of listeners grows quickly.
This was especially bad in synchronous mode because the renders that happen when the promise pings are not batched together. So if a single promise has multiple listeners for the same root, there will be multiple renders, which in turn results in more listeners being added to the remaining unresolved promises. This results in exponential growth in the number of listeners with respect to the number of IO-bound components in a single render. #14429
– Fixing memory leaks issue by clearing fields on unmount.
nulled fields that we were unsure about to the two that we know are safe to
nullout – specifically,
updateQueue. This stops the memory leak we encounter when the associated fibers containing the references to the closures (stored in memoizedState) still exist after being unmounted. #14276
This prevents an obscure issue if you use react-dom/server from 16.6 but react from 16.5 or earlier. We decided to support this a while ago and it's easy to keep working. #14291
- Fix a performance regression in profiling mode. #14383
- Post to MessageChannel instead of window.
Scheduler needs to schedule a task that fires after paint. To do this, it currently posts a message event to window. This happens on every frame until the queue is empty. An unfortunate consequence is that every other message event handler also gets called on every frame; even if they exit immediately, this adds up to significant per-frame overhead.
Instead, we'll create a MessageChannel and post to that, with a fallback to the old behavior if MessageChannel does not exist. #14234
- Reduce serialization overhead.
In the process of switching to MessageChannel, it seems the postMessage call was modified to pass "*" (originally the target origin value from window.postMessage). This actually ends up triggering serialization, whereas passing undefined bypasses.
To save some investigation, passing a Number like 0 still incurs serialization overhead - undefined has special behavior. #14249
- Fix fallback to
setTimeout in testing environments.#14358
- Add methods for debugging.
pauseExecution: pauses the scheduler from making progress running subsequent callbacks in the queue.
continueExecution: continues executing callbacks from the queue.
dumpQueue: returns an array of all scheduled callbacks.
Note: at the moment tests don't pass, because
packages/scheduler/src/__tests__/SchedulerUMDBundle-test.internal.jsensures the APIs exported across different modules is consistent, but I only added the functions to
React Hooks feature was supposed to be released in this version. Unfortunately that was delayed because of the
React.lazy() issues which had to be fixed.