A new React version was released in March 2022, offering several recent changes and providing a foundation for future updates. Let’s briefly dive into these changes and see how we, developers, can make the most of them.
React 18 has some default performance optimization, and the update is pretty straightforward. If we want to upgrade React to version 18, we first need to update the current version of React and ReactDom. We can change React and ReactDom versions in “package.json” and run npm install. or run command – “npm install react@latest react-dom@latest.” This will update React and ReactDom versions.
React 18 has a new root API, and we need to make some changes in our entry point (index.js file):
That’s all. After we make these changes, we can start an Application. React 18 did not introduce any dramatic changes, but there could be cases when our app can break after an upgrade, so we need to be more cautious when we update a production codebase.
Concurrency – The most important addition in React 18 is concurrency. What is concurrency? A fundamental property of Concurrent React is that rendering is interruptible. Creator of React Dan Abramov uses phone calls as an analogy to explain concurrency – “No concurrency means that I can have only one phone conversation at a time. If I talk to Alice and Bob calls me, I have to finish the call with Alice before I can talk to Bob. Concurrency means that I can have more than one conversation at a time. For example, I can put Alice on hold, talk to Bob for a bit, and then switch back to talking to Alice”. React 18 exposes hooks to implement new concurrency features.
useTransition – To translate analogy, in React’s case, “phone calls” are state updates. By default, all state updates are considered urgent. However, we can use useTransition to mark some state updates as low priority, which can be helpful when we want to implement, for example, search functionality. useTransition hook helps us avoid typing lags and makes UI updates more user-friendly.
useTranstion hook returns an array. The first value of the array is isPending boolean, indicating that a transition is active to show a loading state. The second value is startTransition function, which takes a single callback. We can pass state updates to this callback and mark these updates as non-urgent.
useDefferedValue – useTranstion and useDefferedValue broadly have the same behavior. useDefferedValue defers a value instead of state updates. useDefferedValue accepts a value and returns a new copy of the value that will defer to more urgent updates. If we don’t have access to state updates or want to defer a value, we can use useDefferedValue.
Some React libraries use undocumented API to force “setState” outside event handlers to be batched. With React 18, this isn’t necessary anymore.
Think that’s all? Almost there.
If you use useEffect with React 18 and pass an empty dependency array, you may be surprised that it runs twice in development mode.
That is because, with Strict Mode in React 18, React will simulate unmounting and remounting the component in development mode for better performance.
Before React 18
After React 18
How can we solve this? One approach is removing the strict mode, which I wouldn’t recommend. The second solution below is Dan Abramov’s answer to this exact question.
As he said, there is no harm from an extra fetch call in development mode. However, it is also a good idea to use fetching libraries like “React Query” or “SWR” for enterprise projects.
React 18 introduces suspense for data fetching, but this feature is not fully supported yet. Data fetching is not the primary purpose of the useEffect hook, and we need to consider a few factors when using useEffect for data fetching.
And now that’s all, folks. Happy coding.
Written by Shanshe Kenkadze
Get in touch
Business development manager
Business development manager