May 10th 2022. Update: We updated the post with the news about the breaking change in types, and to include a quote from another one of our React developers.
November 2th, 2022. Update: We updated the post with our take on the proposed "use" hook.
January 10th, 2023. Update: We updated the post to include information about the useLayoutEffect hook.
Summary
React, Facebook’s library for building user interfaces, has just received its next major lifting. There is plenty to be excited about, starting from the new Concurrent Rendering, via new hooks, ending with a compiler for React which we may or may not see. Importantly, according to one of our React Developers, Alexandru Gherasim, the library “still provides the same freedom of choice it used to give to devs. The major difference I see is that the maintainers have recognized the lack of a good way to tackle all the different aspects of a web-app that React could possibly solve.”
As with every major new release, there is a lot to unpack, and before we do that, let’s answer a key question: “how hard is it to upgrade.”
The process is supposed to be straightforward. As much so, that the team claims that migrating most apps will not take more than a single afternoon. You get access to numerous new functionalities “with minimal or no changes to your application code”. The new functionalities include the all-new Concurrent Rendering. In case you wondered, “[w]e [the React team at Facebook] successfully shipped concurrent features to tens of thousands of components at Facebook, and in our experience, we’ve found that most React components “just work” without additional changes.”
Of course, if you want to make use of all the new possibilities, then you will have to spend some time refactoring. The time investment will be worth it, as you will be now able to control which component updates when, among other features.
Short answer: highly unlikely, if you are using plain JavaScript. If you are using TypeScript, then you need to make sure to upgrade your types, and run an automated tool we linked below. Long answer: there could be times, when your app would break though, yes.
One of the more common cases, for your app not working, is the new, stricter, Strict Mode. In case anything fails with the upgrade, be sure to check whether your app has it enabled. Even though we know what you’ll think, consider dropping it for some time.
Another breaking change is the issue with the types. As it turns out, compilers all around the world started a strike. There are some things that React developers need to look out for now. One example is the change in some more common types. Based on what eps1lon wrote on GitHub in “[react] React 18 types #56210”, FunctionComponent replaced StatelessComponent, SFCElement is out, and FunctionComponentElement is in. Some types are without a replacement, such as Props or RefForwardingComponent. All details are in a GitHub Pull Request we are linking to here. Of course, developers would not be developers if they did not create an automatic tool to fix their code. Here, the same user came in clutch, creating types-react-codemod available here. If your app doesn't compile after the upgrade, be sure to check out both of these resources.
There are few breaking changes that will make developers shed tears of happiness. React 18 drops support for Internet Explorer 11, even before the scheduled end of support from Microsoft. While you would expect the bundle size to decrease, it did not, not yet. The code is still there, and the team will drop it at a later date. For most of the teams, that is great news. For most, as some businesses still need to support Microsoft’s browser: such as the ones working for the UK’s NHS.
Other breaking changes? There are some you must be aware of:
With this crucial topic out of the way, let’s get into the details of new features.
React is a kind of library to give you the building blocks without instructions on how to build something with it the efficient way. Some love it, and some hate it: there are countless solutions to the same problems. On the other hand, that also means you might build something without realizing you have just made a horrible mistake, or not realizing that your solution is suboptimal.
This is why, the engineering team at Facebook is working on an experimental compiler called “React Forget.” On the surface, the concept seems sweet. A compiler taking care of optimization for you? Automatically? How cool is that? The issue is, it’s experimental tech, AND we don’t even know whether it will be released to the public. Moreover, other libraries, such as Vue.js, do all that optimization for you, “free”, AND are faster than React.
Being an open-source project, React has to be in touch with the community, which takes part in the creation of the library. Starting from last year, there is a React 18 Working Group. Compared to the size of the React community, it’s small, and invite only.
It’s great to see the team from React take feedback on board from a “representative” group of developers. After all, the rationale behind the library was to share the project with the outside world to make problem-solving easier for many. On the other hand, one has to wonder whether the wider community did not deserve at least a vote for the working group members. After all, many have committed countless hours to improving the library.
This feature here can bring a lot of value, effortlessly. Seriously.
If you were using a relatively “clean” version of React, you know, very well, that you had to bundle many libraries with your code. Transforming markdown to HTML, or rich text to HTML, was something that you often had to do on the client, since the React is… a client-side library. Not anymore, as Server components are in an alpha stage. You may put heavy code in your server components, thus adding 0 bytes to what your users load. One might even say, that we are now dealing with a full-stack library, instead of a hyper-focused front-end one.
Server components will for sure decrease bundle sizes across the board, and significantly improve the performance of countless websites out there. Marcin Dąbrowski, ITMAGINATION's Chief Innovation Officer, agrees, saying “React's brand-new Server Components are a great way to reduce the size of your applications.” The only catch is that they are not stable yet, so we would not advise you to use them now. The time for it will come after a minor, 18.x, release. Watch our blog, as we will update you when client components will be ready to use in production. Alternatively, if you are brave enough, you may start hacking now.
We have to admit, Suspense is nothing new. It’s an “old” feature, introduced in React 16.x. Until now, the functionality was rather limited, however. Not anymore.
Suspense lets you show user interfaces faster. Paradoxically, perhaps, as the new feature allows you to show your components sooner to display a loading state, such as a spinner. Nevertheless, this is a major improvement to the user experience: now your users will at least get some feedback; they will know something is happening behind the scenes. Crucially, your components may now render independently of each other.
Server-side rendering (SSR) is a practice, where we render our app on a server before sending everything to a visitor. There are several problems with the approach, though one phrase summarizes them pretty well: “all or nothing.”
1. The whole page needs to be prepared before we send it;
2. The whole page needs to be sent to the browser before we can show it;
3. The whole page needs to be made interactive before we can have our users interacting with it.
As you imagine, that’s not the most efficient approach.
Picture a blog. A blog, that we render on the server, for the best SEO. At times, there are pieces which are both lengthy, and interactive. Naturally, you want to show your readers the content you have for them as fast as possible. The problem is, until now, the body of text would block the rest of the piece from showing up. Furthermore, it would then also block the entire page from being interactive. Not ideal, huh? What if, instead of waiting for one troublemaker, we would first show the title, description, and other parts, while we wait for the actual content to load. We could even go a step further. First, we show the bare minimum, while we are still waiting for the interactive elements to load. Even though that will not be a full experience, we will keep our reader busy, giving us time to bring the heavy pieces together. Suspense keeps components hydration (adding interactivity) independent.
To illustrate the point for the React audience, React’s team featured Shaundai Person, a senior software engineer at Netflix, on their YouTube channel. The entire video highlighted how much Suspense means for the video streaming platform, and other heavier apps. The team at Netflix should know a thing or two about optimizing web apps. By the very nature, VoD platforms are heavy and sluggish, and yet you may make them feel light and snappy. The key is to they substitute the heavier bits and pieces with placeholders. Then, as soon as the missing data is ready, your app will provide the full experience for you.
This pattern enables countless companies to reduce bounce rates, time to interactive, and others. It’s of utmost importance your teams make use of the new, improved, Suspense.
The team at Facebook prepared the app for the future, and prepared it for future performance improvements. This is why, there is a new, development-only, check. Quoting the documentation, “[t]his new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.” For more details, go here.
Automatic Batching refers to automatic batching (grouping) of updates to the state. Currently, more often than in the past, multiple state updates will execute together. Previously, components would re-render more times than necessary, causing problems, and slowdowns. Quoting the documentation, “[t]his is a breaking change, but we expect this to result in less work rendering, and therefore better performance in your applications.”
If you want to opt out of the change, you may do so, using flushSync. As the new mechanism promises to bring performance improvements, we discourage you from doing so.
For a deep dive on the topic, please refer to this discussion on GitHub.
Concurrent rendering is a new way of components to render, and it will bring many changes for the better. Concurrency is the execution of logic out of order, without changing the final result. It’s about dealing with many things at once.
Initially, there was a rumor saying that “Concurrent Mode” will break your apps, and you will need to rewrite your app because it would not work anymore. As you can easily guess, the community was not too thrilled about it. Luckily, the team behind the project changed their minds, and went for a gradual approach, instead.
Finally, the feature is a powerful new way in which React apps function. What we see is just a beginning, however. The new features will become the new foundation for future improvements as well. To quote the React documentation:
“Concurrent rendering is a powerful new tool in React and most of our new features are built to take advantage of it, including Suspense, transitions, and streaming server rendering. But React 18 is just the beginning of what we aim to build on this new foundation.”
In case you are wondering whether full-stack frameworks, such as Next.js, are going away, then we have good news for you: they aren’t. It wasn’t even the intention of the developers of Facebook’s open-source libraries to replace them. In fact, one of the engineers at Shopify had a chance to speak at React Conf 2021. During the talk, we could find out that the integration of server components, and all new features isn’t where it needs to be for a universal adoption.
Same with Next.js: React 18’s server components, or React 18’s “Streaming” capabilities are in an alpha, and it would take a brave team to start using them in production. On the other hand, there is a saying that fortune favors the brave.
If you can make the new features work, and if you can afford for occasional breakdowns, then make sure your business upgrades to the new version. Version 18 is worth it.
We could not be considered objective if we did not list at least a few of the common critiques of React, and its new version.
For one, what started out as a small library, turned into a behemoth, which now also includes some full-stack capabilities (!). People like to make fun of Angular (including the author of the text), but at the very least it goes into one direction, and it stays there. It was supposed to be a gigantic framework for corporate apps, and it is just that.
Secondly, new hooks introduce more complexity into an already complex-despite-looking-simplistic React. Furthermore, we (often) can’t write regular JavaScript anymore. Typically, instead of writing just whatever we want, we have to go ahead and wrap everything in several hooks to make sure we do everything the “optimal” way. That might introduce some subtle bugs that are hard to track, and more. For some who love hooks, and cannot get enough of them, please take a look at the “React Forget” video. As an alternative, people who do mind optimizing everything manually, check out Vue.js. It does optimizations under the hood, freeing you to do the actual job. You can write jsx with it as well.
Lastly, React is becoming a black box. There are some issues about the library that devs don’t understand, or they think they understand, and then it blows up in their faces. Don’t take it from me, take it from Jared Palmer and his article… from 2019.
If these points discouraged you from using React, feel free to schedule a “no hidden catch, no strings attached” consultation with one of our architects for possible alternatives and whether Facebook’s library is the right fit.
The Facebook (Meta) team has prepared a new use of the hook to simplify the use of promises in React Client Components. To use promises in a component in the past you had to use the useState hook and pass values from promises via state. Now you can use the use hook to get the value you got and assign it directly to a variable.
Additionally, the use hook has another function. You can use it nested in blocks, loops, and conditions to wait for data load without splitting your logic into separate components.
Use can be used to handle Context the same as useContext but moreover can be used conditionally. In the future use should handle another types of "wrapped" values like observables or store, but it is song of the future.
The new hook is a well thought out solution, and might help with data fetching, and working with them.
We will be able to say more for sure, when the plans get implemented, and everything will work as expected.
There is a chance you could be confused about when to use useEffect, and when to use useLayoutEffect. It's ok!
Both of these hooks handle side-effects in React and have an identical signature. That's not helpful now, is it?
The main difference is that useEffect runs asynchronously after a render is painted to the screen, unblocking the browser paint process whereas useLayoutEffect fires synchronously after all DOM mutations.
useEffect should be used for most cases such as fetching data or setting up event handlers, while useLayoutEffects should be used when mutating the DOM (like getting scroll position or other styles for an element) or involving animation. In React 18, only for discrete events will useEffect fire synchronously; otherwise it will defer effects until after paint. In another words, the difference between them is the timing of their invocation.
Generally, it's recommended to stick with using just the useEffect hook unless there is an animation or a DOM mutation that needs to happen immediately.
React is, undoubtedly, the ruler of the current web. Of course, it is not without flaws, and some points that the critics raise are obviously valid. No library is without a flaw, however. Programming, in the same way as life, is an art of making trade-offs. The question is whether you are making the right ones. The majority of modern-day web developers tend to agree.
It’s no wonder that the entirely new industry, Web3, picked Facebook’s library to be its powerhouse. No matter the industry, it’s the default choice for the majority of companies building new products. We may go even further: React Native, which bases on React, is a great choice for those building cross-platform mobile apps.
The new version, version 18.0.0, will make new (and old) apps more feel more snappy: only if the teams apply the aforementioned new features correctly. We might also load less JavaScript on countless websites, and be able to interact with content much quicker. All thanks to the improvements coming from React 18, and all thanks to the gradual adoption approach. The gradual approach has its drawbacks, however. As Ludomir Skóra, a senior front-end developer at ITMAGINATION, pointed out, the newest release feels like an alpha, although it's important that the library keeps evolving. He also shares the same curiosity of many programmers; the eagerness to see how the features will develop further, and what we will get down the line.
To end with, we would like to end with some words from Alexandru:
Does React have increased the amount of concepts to learn? Yes.
Did it make the learning curve a bit steeper? Yes.
Does it provide a uniform way to tackle critical aspects of performant web apps? Absolutely, and it's better than it used to be.
Does it deny the freedom to swap between different solutions for some special use-cases? Not in the slightest.
In case you are one of the few companies struggling with the migration, or are looking for web app development partners, feel free to contact our experts. If you are a React developer, you might want to explore how to use AI while writing web apps.