· JS, React, Typescript, React 18, ceateRoot API

React moved into adulthood. Reflections on updating React to v18

React 18 is out. I mean… it’s been available for over four months and I’ve just finished a kinda challenging process of migration from 17 to 18 in a huge JS app which is a mature SaaS product. I guess I completed it since you never know when the monster named tech debt could bite you. Anyways, I’d want to share some views on updating to 18v here, in the hopes that someone would find them useful.

If you’re unfamiliar with the topic of version 18, read the official docs of the latest React.

The new API

Before considering bumping, please note - React’s most significant API has been modified. This means the commonly known and essential root mounting with ReactDOM.render is deprecated. Of course, it’s still supported (due to backward compatibility), but it produces irritating warnings in production env and floods specs run. Hint: a crazy spy may save us from the warnings flood in a spec run, but nothing will help in production except replacing the old API with the desired new ReactDOMClient.createRoot.

Only the use of the createRoot API enables all React 18 features; otherwise, it behaves like v17. It’s not worth updating if you don’t have time to refactor.

I once went to a tech conference where one of the speakers was convincing the audience that it’s not crazy to consider releasing tech products with a failure. Failures bring crises, crises - the best solutions. I don’t take a stupid warning a failure, but what is most important the API replacement may fail in big JS projects of course. I assume the cost of the bump, disappointment, wasted time, tech debt to pay off etc. Maybe it’s not worth making it at this time, following the YAGNI principle. So, before updating the API in crucial parts, consider what would your customers do if an app didn’t work for one hour? Especially when test coverages are not credible and only a happy path is checked on your CI. That was not my case, but it’s worth asking questions: is it a good time to do such updating? Do I really need the React 18 features now? What profits does it bring to my project? Please take such updating as a huge task to accomplish.

Code updates

Apart from replacing ReactDOM.render with ReactDOMClient.createRoot, the whole bump entails code updatings, like:

Types updates

If you use Typescript with React as I do, you must fix the issues that the most recent types package will point up, like:

Aside from code updates, the React types must be modified to reflect at least the primary changes. Regrettably, for large JS projects, TS is more rigorous now, and does not allow things that were permitted in v17 or below. This should be considered when comparing the TS rules followed in an app. What if the majority of the components need to be refactored or updated?

Strict mode behavior

The next, interesting thing is the strict mode that v18 offers. React, as docs states, in the further releases wants to ensure the reusable state. For that purpose, the newest StrictMode adds ‘strict mode effects’ that intentionally call side effects double times (mounting, unmounting, mounting) in dev mode. Some effects may not work as expected eg. subscriptions might be not properly destroyed in clean-up functions. This may make the strict mode off until callbacks are adjusted to the double invocation. If you enabled the mode in v18, the not properly cleaned subscriptions may entail additional refactorings.

More pieces of advice

Here are some pointers for anyone thinking about bumping:

Summary

What I like about software engineering is that it can be done incrementally. I recommend having a reliable plan in place to change the React version of an app smoothly and easily. The way that nobody noticed but your CI tools on performance score. In my case that was the most challenging React update I’ve ever made. If you are on the same task and need advice, you can try to reach out to me.

React 18 is great ;-)