Skip to content

Conversation

@serhalp
Copy link
Member

@serhalp serhalp commented Jun 5, 2025

Summary

This adds support for React 19 to all Gatsby packages, while maintaining support for React 18.

This is not a breaking change.

All packages' peer dependencies on react and react-dom have been extended from ^18.0.0 to ^18.0.0 || ^19.0.0.

All existing stable Gatsby functionality is intended to work with React 19.

Upgrade Guide

To upgrade to React 19, first upgrade gatsby and all your gatsby-* dependencies to the latest version. Then, follow the React 19 upgrade guide. No other changes are required.

Please note:

  • Some new React 19 features may not be available yet via Gatsby.
  • Gatsby Partial Hydration, an experimental feature for three years now, is known to be incompatible with React 19 at this time.

(TODO call out the new global error handling stuff)

Implementation

This PR configures CI to run the existing development-runtime and production-runtime e2e test suites against both React 18 and 19.

fix(gatsby-plugin-image): work around a regression in React 19 core

There is an undocumented change in behaviour in React 19: facebook/react#31660. Basically, in previous versions, an unchanged dangerouslySetInnerHTML.__html would not result in a re-render, but in React 19 referential equality of the dangerouslySetInnerHTML object is used instead.

The gatsby-plugin-image implementation fundamentally depends on the previous behaviour, so that our own innerHTML updates do not get clobbered by a reset to this dangerouslySetInnerHTML placeholer value.

As a workaround, this commit memoizes the object with useMemo().

This is safe for React 18 as well.

fix: replace usages of __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 😶

There was one use of React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?.ReactDebugCurrentFrame?.getCurrentStack(). React 19 introduced React.captureOwnerStack() which we'll now use instead if available.

(TODO describe the react-refresh / partial hydration stuff)

@gatsbot gatsbot bot added the status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer label Jun 5, 2025
@serhalp serhalp force-pushed the feat/support-react-19 branch 2 times, most recently from d52b12d to 24546b0 Compare June 6, 2025 21:52
@serhalp serhalp force-pushed the feat/support-react-19 branch 5 times, most recently from 6ab44fb to 6680733 Compare August 5, 2025 19:55
@serhalp serhalp changed the title feat: wipwipwip feat: support React 19 Aug 5, 2025
@serhalp serhalp force-pushed the feat/support-react-19 branch 12 times, most recently from 3b417a1 to ccc2189 Compare August 8, 2025 12:53
@serhalp serhalp linked an issue Aug 8, 2025 that may be closed by this pull request
2 tasks
@serhalp serhalp force-pushed the feat/support-react-19 branch 4 times, most recently from 7f66511 to 3797d4d Compare November 14, 2025 14:52
There is an undocumented change in behaviour in React 19:
facebook/react#31660. Basically, in previous versions, an unchanged
`dangerouslySetInnerHTML.__html` would not result in a re-render, but in React 19 referential
equality of the `dangerouslySetInnerHTML` object is used instead.

This code fundamentally depends on the previous behaviour, so that our own `innerHTML` updates do
not get clobbered by a reset to this `dangerouslySetInnerHTML` placeholer value.

As a workaround, this commit memoizes the object with `useMemo()`.

This is safe for React 18 as well.
@serhalp serhalp force-pushed the feat/support-react-19 branch from 5456193 to 283d610 Compare November 19, 2025 22:07
@serhalp serhalp force-pushed the feat/support-react-19 branch from 283d610 to 3be685d Compare November 19, 2025 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

React 19 support

2 participants