If you’re like us, you’re eagerly awaiting the release of the new version of React (commonly referred to as React Fiber). While it’s anybody’s guess when it will go GA, there are some things that you can do to get ready.
We don’t intend to comprehensively go into the differences between React Fiber and the current React architecture (code named React Stack), but if you haven’t yet seen it you should watch Lin Clark’s talk at React Conf’17. She does a great job using illustrations to explain the interrupt model, architectural differences, and visually depicting why the new version is code named Fiber.
The promise of smoother transitions alone are likely worth the price of upgrading, particularly for the complex and scientific applications our customers demand. Fiber will undoubtedly allow us to build better user experiences for our customers with better control on prioritizing rendering updates and a smarter interrupt model. However this upgrade path may be tricky.
In terms of getting ready for Fiber, Lin does a good job warning React developers to be aware of how they use setState(). Many React developers don’t realize that setState() can be passed either an object or a function. When using the object approach, the argument represents changes to be made to a component’s state. Whereas in the functional approach, a function is provided that will actually compute the new state.
The functional approach is the preferred use of setState going forward, and the object argument version may eventually be deprecated in React Fiber, even though it is the most commonly used method today when updating component state.
The React team’s reasoning for functional setState is sound because it enables batching updates for more efficient rendering, whilst this is essential in React Fiber’s new reconciliation algorithm it can also have an impact now in React Stack. There are other benefits from adopting functional setState early including too; a cleaner access pattern for existing state, along with improved testability and more potential for code re-use. However, for the unprepared, this will come as an unwelcome surprise and a tedious upgrade path.
When upgrading React, explicitly deprecated features tend to be pretty straightforward and easily called out with tooling like eslint. However some changes can be more insidious as they may have side effects that will be difficult to spot or reliably reproduce.
Take componentWillUpdate vs componentDidUpdate. In React Stack, these 2 calls would always fire on a 1:1 ratio and are often used interchangeably to run code in response to a component updating. However imagine a case in React Fiber where, due to a higher priority task interrupting componentWillUpdate(), it is unexpectedly run more than once. Yikes!
To illustrate the point, imagine a component tracking the number of times the user changes an input along with a counter of the number of changes made.
In the first instance, this._numChanges could be incremented multiple times during the same render cycle due to the new interrupt model:
Using componentDidUpdate would not suffer the same issue because it will only be called after the update has completed:
In general, the componentWill* lifecycle hooks aren’t a safe place for code with global side effects and should be used sparingly. This hasn’t changed with React Fiber, but Fiber will make the consequences of misusing these hooks even greater, leading to more nefarious bugs.
We spend a lot of time with corporate customers trying to get new systems and technologies to play nice with existing compute infrastructure. Modernizing is a non-trivial concern and frequently cited as one of the main reasons projects with new technologies fail. Rarely do you start with a blank whiteboard. We’ve got several clients running their business on React Stack now. Whether or not to upgrade (and when) will need to be thoroughly thought through. Stay tuned for our next blog in the series where we describe the tooling we use to find these little time bombs in our code.