03 / 03

Discuss what changes and updates were introduced in react 16,17,18 and 19 versions in detail

React 16 introduced Fiber, Error Boundaries, and Hooks; React 17 focused on gradual upgrades and event delegation changes; React 18 added Concurrent Rendering, Automatic Batching, and SSR Streaming; React 19 brings Actions, the React Compiler, and the use() API.

The evolution from React 16 to 19 represents a significant shift in how we build user interfaces. React 16 laid the foundation for asynchronous rendering with Fiber and introduced Hooks, which revolutionized state management and logic reuse. React 17 served as a "stepping stone" release, making it easier to upgrade React itself without breaking changes. React 18 introduced Concurrent Rendering, enabling React to prepare multiple versions of the UI simultaneously and improving perceived performance. React 19 builds on these foundations with Actions for simplifying data mutations, the long-awaited React Compiler for automatic memoization, and the new use() API for reading resources directly in components.

React 16 (2017–2019): The Foundation of Modern React

React 16, released in September 2017, was a major rewrite of React's internal architecture. Its most significant change was the introduction of Fiber, a complete reimplementation of the reconciliation algorithm that enabled asynchronous rendering . Fiber broke the rendering work into chunks, allowing React to prioritize updates and avoid blocking the main thread for long periods. This paved the way for Concurrent Rendering in later versions.

React 16 also introduced Error Boundaries via the componentDidCatch lifecycle method, which prevents a JavaScript error in one component from unmounting the whole React tree . Other key additions included the ability for render to return arrays and strings (eliminating the need for wrapper divs), the Fragment component with shorthand syntax <>...</>, and the official createRef API. React 16.3 added the new Context API (createContext, Provider, Consumer), replacing the unstable legacy context . React 16.6 introduced React.lazy and Suspense for code-splitting, and finally, React 16.8 (February 2019) introduced Hooks—useState, useEffect, useContext, useReducer, etc.—allowing function components to have state and side effects, a paradigm shift that has become the standard way of writing React components .

React 16 introduced following major updates:
  1. 1

    React fiber: a new reconciliation engine. Before Fiber, React’s update process was synchronous—once it started rendering, it couldn’t be stopped until it finished. Fiber introduced asynchronous rendering, allowing React to pause, prioritize, and reuse work. It enabled the ability to split rendering work into chunks. High-priority updates (like user typing) can jump ahead of low-priority updates (like rendering a large list).

  2. 2

    Error Boundaries, componentDidCatch: React 16 introduced Error Boundaries, which are class components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the crashed component tree.

  3. 3

    Portals: Portals provided a first-class way to render children into a DOM node that exists outside the hierarchy of the parent component. This is particularly useful for modals, tooltips, hovercards

  4. 4

    Fragments: you could now return multiple elements without a wrapper div.

  5. 5

    Strings and Numbers: Components could finally return raw text or numbers without wrapping them in a <span>

  6. 6

    Arrays: You could return an array of elements (though each needed a key).

  7. 7

    Custom DOM Attributes: In earlier versions, React would ignore unknown DOM attributes. If you wrote <div mycustomattribute='foo' />, React would strip it out. React 16 changed this to allow all custom attributes to pass through to the DOM, which is helpful for using non-standard HTML attributes or integrating with third-party libraries.

  8. 8

    Server-Side Rendering (SSR) Improvements: React 16 included a completely rewritten SSR engine that was significantly faster. It added support for streaming, allowing the server to start sending HTML to the browser as soon as it's generated, rather than waiting for the entire page to render. It became more resilient to mismatches between the server-rendered HTML and the client-rendered output.

  9. 9

    Reduced File Size: Despite adding these features, React 16 was actually smaller than version 15. The react and react-dom packages combined saw a size reduction of roughly 32% (34.8kb gzipped, down from 44.7kb).

React 17 (2020): The Stepping Stone Release

Released in October 2020, React 17 was unusual because it added no new developer-facing features . Instead, its primary goal was to enable gradual upgrades, allowing applications to run multiple versions of React simultaneously and migrate piece by piece . This was made possible by changes to event delegation—React 17 no longer attaches event handlers at the document level but instead attaches them to the root DOM container into which the React tree is rendered . This change improved compatibility with other frameworks (like jQuery) and made embedding React into legacy applications safer. React 17 also introduced a new JSX transform that automatically imports the necessary functions, reducing boilerplate, and improved stack traces for debugging production errors by stitching native JavaScript stacks together .

React 18 (2022): Concurrent React

React 18, released in March 2022, introduced Concurrent Rendering, a new behind-the-scenes mechanism that enables React to prepare multiple versions of the UI at the same time . This allows React to interrupt rendering, prioritize urgent updates (like user input), and keep the UI responsive even during heavy computations . Key concurrent features include Transitions (useTransition and startTransition), which mark updates as non-urgent and allow React to keep displaying the current UI while preparing the new one, and useDeferredValue, which defers re-rendering a non-critical part of the UI .

React 18 also introduced Automatic Batching, which batches all state updates that occur within the same event loop (including promises, timeouts, and native event handlers) into a single re-render, improving performance . For server-side rendering, React 18 added Streaming SSR with Suspense, allowing the server to stream HTML in chunks and components to be rendered asynchronously without blocking the entire page . The new root API (createRoot and hydrateRoot) replaced ReactDOM.render and enabled concurrent features. New hooks included useId for generating unique IDs for accessibility attributes, useSyncExternalStore for external store integration, and useInsertionEffect for CSS-in-JS libraries .

React 18 introduced following major updates:
  1. 1

    Concurrent rendering: This is the core engine update. It doesn't change your code directly but enables new features that make UIs feel significantly faster. Interruptible Rendering, React can start rendering an update, pause it to handle a high-priority event (like a user click), and then finish the render later. Transitions: You can now tell React which updates are 'urgent' (typing) and which are 'non-urgent' (filtering a list).

  2. 2

    Automatic Batching: Batching is when React groups multiple state updates into a single re-render for better performance. Before React 18 only React event handlers (like onClick) were batched. Updates inside Promises, setTimeout, or native event handlers would each trigger a separate re-render. In React 18: All updates are automatically batched regardless of where they originate.

  3. 3

    New Root API: createRoot(document.getElementById('root'));

  4. 4

    New Hooks: useTransition, useDeferredValue, useId, useSyncExternalStore

  5. 5

    Improved Suspense: Added support for 'Streaming SSR,' where parts of the page can be sent to the browser and 'hydrated' as they become ready, rather than waiting for the entire page to load. Suspense now integrates with useTransition so that switching between tabs or views doesn't immediately trigger a 'loading' spinner if the data is already being fetched in the background.

  6. 6

    Strict Mode Enhancements: In development mode, React 18’s Strict Mode now intentionally unmounts and remounts every component whenever it mounts for the first time. This helps developers find bugs related to 'Effect' cleanup and ensures that components are resilient to being destroyed and recreated (a common occurrence in the new concurrent world).

React 19 (2024–Present): Actions and the Compiler

React 19 introduces several major features that simplify data mutations and improve performance. Actions are a new way to handle form submissions and data mutations using async functions, automatically managing pending states, errors, and optimistic updates . The useActionState hook simplifies form state management, useFormStatus provides access to the status of a parent form, and useOptimistic enables optimistic UI updates .

The React Compiler (formerly known as React Forget) is a build-time tool that automatically memoizes components and hooks, eliminating the need for manual useMemo, useCallback, and React.memo in most cases . This reduces boilerplate and prevents common performance bugs. The new use() API allows reading the value of a promise or context directly within a component, simplifying async data handling and reducing the need for useEffect . Other improvements include refs as props (removing the need for forwardRef), better support for metadata (<title>, <meta>) directly in components, and full integration with Server Components and Server Actions .

Difficulty: 8/10
Topics: concurrent rendering, automatic batching, migration strategy

Scenario Questions

0-2 years experience
  1. 1

    You need to upgrade a small project from React 16 to React 17. What steps would you take to ensure the app continues to work, and what breaking changes should you watch for?

  2. 2

    If you add a new component that uses the new JSX transform introduced in React 17, how does the build setup differ compared to React 16?

2-5 years experience
  1. 1

    Your team is adding a feature that relies on React 18's concurrent rendering, but you notice UI flickering in the browser. How would you diagnose and resolve the issue?

  2. 2

    While migrating a medium‑sized codebase from React 16 to React 18, you encounter warnings about the legacy context API. Explain how you would address them and why it matters.

5-8 years experience
  1. 1

    Design a strategy to incrementally adopt React 18's automatic batching and server components across a large monorepo that still has parts running on React 16. What trade‑offs do you consider?

  2. 2

    After enabling React 19's new concurrent features, your app shows performance regressions under load. How would you profile the problem and decide whether to keep or roll back the changes?

8+ years experience
  1. 1

    As a staff engineer, you need to plan a multi‑team migration from React 16 to React 19 over two years, balancing legacy code, third‑party libraries, and CI pipelines. Outline the high‑level roadmap and governance model you would propose.

  2. 2

    Discuss the architectural implications of adopting React 19's streaming server‑side rendering and selective hydration for a global e‑commerce platform. How does it affect caching, SEO, and team ownership?

Follow-up Questions

  • What specific code patterns would you refactor first?
  • How do you measure the impact of automatic batching?
  • Can you give an example of a fallback plan if a new feature causes regressions?