Skip to content

Migrate to React 19 #2820

Description

@hkfb

Motivation

React 19 has been the current major release for some time, and consumers of @webviz/*
increasingly run it. Today every published package declares "react": "^17 || ^18", so
installing alongside React 19 produces peer-dependency conflicts.

The blocker is that supporting React 19 cannot be done additively: several React 19 changes are
breaking for this codebase, and some of our dependencies only gained React 19 support in major
releases of their own.

Required peer-dependency change (breaking)

All packages need to widen their React peer range:

-"react": "^17 || ^18",
-"react-dom": "^17 || ^18"
+"react": "^18 || ^19",
+"react-dom": "^18 || ^19"

This drops React 17 support, which is why it warrants a major release.

Dependencies that must be upgraded

React 19 support forces the following bumps, because the current pinned versions declare
React 18 (or lower) peers:

Package From To Reason
@equinor/eds-core-react ^0.36.0 ^2.6.1 React 19 peer support
@equinor/eds-icons ^0.21.0 ^1.5.0 required by eds-core-react v2
@emerson-eps/color-tables ^1.0.x ^1.1.0 React 19 peer support
react-resize-detector ^11 ^12 React 19 peer support
@cypress/react18 ^2.0.1 @cypress/react@^9 see below

Note on Cypress: @cypress/react18 pins react: ^18 and is the deprecated split package. There is
no @cypress/react19 package — Cypress consolidated back to @cypress/react, whose v9
declares react: ^18 || ^19. So the correct move is @cypress/react18 -> @cypress/react@^9.

Code changes required by React 19

  1. New JSX transform. Set "jsx": "react-jsx" in tsconfig.json and
    runtime: "automatic" in the Babel preset, then drop the now-redundant
    import React from "react" statements. ESLint needs plugin:react/jsx-runtime so
    react/react-in-jsx-scope stops firing.
  2. The global JSX namespace was removed from @types/react. All JSX.Element
    annotations must become React.JSX.Element.
  3. Ref callbacks may no longer return a value. Arrow-function refs of the form
    ref={(el) => (this.foo = el)} are now type errors and must use a block body.
  4. defaultProps on function components was removed. Remaining usages must move to
    default parameter values.
  5. propTypes no longer contribute to inferred prop types. JSX.LibraryManagedAttributes
    dropped its propTypes support, so props declared only in propTypes (for example id on
    WellLogViewer, WellLogView and SyncLogViewer) must be added to the TypeScript props
    interfaces. WeakValidationMap was also removed from @types/react.
  6. ReactElement's default props generic changed from any to unknown, so code reading
    element.props.* (e.g. DashSubsurfaceViewer) needs explicit typing.

Test-suite impact

  • @equinor/eds-core-react v2 uses the native Popover API. jsdom implements neither
    showPopover nor hidePopover, so tests rendering EDS menus fail with
    refs.floating.current?.hidePopover is not a function until a polyfill is added to the Jest setup.
  • EDS v2 changes rendered markup, so a number of Jest snapshots need regenerating.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions