Skip to content

Feature: React 19 Upgrade - #951

Draft
wadebekker wants to merge 3 commits into
developfrom
feature/react-19-upgrade
Draft

Feature: React 19 Upgrade#951
wadebekker wants to merge 3 commits into
developfrom
feature/react-19-upgrade

Conversation

@wadebekker

Copy link
Copy Markdown

Description of the Change

Upgrades the entire monorepo — all 5 published packages and all 8 example/test projects — to React 19, via a single root-level overrides block plus the supporting changes needed to actually build and run cleanly under it.

  • @types/react/@types/react-dom and testing-library versions bumped workspace-wide
  • Fixed React 19's removal of the global JSX namespace (JSX.Element) in core, epio-search, and block-primitives
  • Bumped @wordpress/* and @10up/block-components in block-primitives to versions that declare React 19 support
  • Pinned webpack/webpack-dev-server versions needed to keep wp/10up-theme's build working under the shifted dependency graph (tracked upstream: 10up/10up-toolkit#479 for the dev-server issue)
  • Removed now-dead propTypes/defaultProps usage from the two multisite Pages Router projects — these are silently ignored under React 19, so they no longer served any purpose
  • Deduped package-lock.json from a clean install (collapses several duplicate nested @wordpress/*/redux copies that accumulated across the many incremental installs made while working through this)

A real bug found and fixed, not just a version bump

Adding a Universal Block (tenup/hero) in the WordPress block editor crashed with Objects are not valid as a React child. Root cause: block-primitives compiled its JSX using React 19's "automatic" runtime, which bundles its own copy of react/jsx-runtime. WordPress's own build tooling (@wordpress/dependency-extraction-webpack-plugin) externalizes react/react-dom to WordPress core's globally-provided React, but has no equivalent handling for react/jsx-runtime — so the block's bundle ended up creating elements tagged by React 19 that got handed to WordPress core's actual React 18.3.1 reconciler, which doesn't recognize them as valid.

Fixed by switching block-primitives to the classic JSX transform (React.createElement), which resolves through the externalized global consistently. Confirmed fixed end-to-end: the Hero block now works correctly in both the wp-admin editor and the headless Next.js frontend, with zero console errors.

Testing done

  • npm run build / npm run test / npm run lint — clean (15/15, 7/7, 14/14) from a fully fresh node_modules install, not just incrementally
  • All 8 example/test projects manually smoke-tested in a real browser (routes, hydration, console)
  • The WordPress block editor manually verified for the one package with a real, previously-unverified React 19 compatibility question (@10up/block-components)
  • Several surprising findings along the way were verified as pre-existing rather than assumed — confirmed by reproducing them against the original pre-upgrade code in isolated worktrees, or checking directly at the WordPress REST API level

Out of scope/Not yet covered in this PR

  • docs/ (Docusaurus) — not part of this workspace, left on React 18
  • The CI Node 16.x matrix cleanup and package changesets are tracked as follow-up, not blocking this PR

Test Plan

  • npm install && npm run build && npm run test && npm run lint
  • Spot-check a couple of the example projects locally
  • If touching Universal Blocks: verify the tenup/hero block still works in wp-admin

Changelog Entry

Changed - Upgraded to React 19 across all packages and example projects.

Credits

Props @wadebekker

Checklist:

Bumps react/react-dom to 19 across every package and project via a
single root-level override, plus the dependent changes needed to
actually build and run cleanly under it:

- @types/react and testing-library versions bumped workspace-wide to
  their react-19-compatible releases
- fixed react 19's removal of the global JSX namespace (JSX.Element)
  in core, epio-search, and block-primitives
- switched block-primitives to the classic JSX transform, since its
  compiled output gets bundled directly into wp-admin block-editor
  builds, where react itself is externalized to WordPress core's
  own globally-provided copy but react/jsx-runtime is not - the
  automatic runtime was silently creating a dual-react-version
  conflict that crashed the block editor
- pinned webpack and webpack-dev-server versions needed to keep
  wp/10up-theme's build working under the shifted dependency graph
- bumped @wordpress/* and @10up/block-components in block-primitives
  to versions that declare react 19 support
propTypes/defaultProps on function components are silently ignored
under react 19, so they no longer serve any purpose in these two
projects. Removes the prop-types dependency entirely and disables
the now-permanently-unsatisfiable react/prop-types eslint rule for
both projects.
Regenerated package-lock.json from a fully clean node_modules install
rather than the accumulated result of many incremental installs made
throughout the upgrade. Collapses several duplicate nested copies of
@wordpress/data, @wordpress/element, and redux that had built up along
the way into single shared copies.
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 864a717

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
headstartwp-app-router Ready Ready Preview, Comment Jul 20, 2026 11:30am
headstarwp Ready Ready Preview, Comment Jul 20, 2026 11:30am

Request Review

@wadebekker wadebekker self-assigned this Jul 20, 2026
@wadebekker
wadebekker requested a review from chriseagle July 20, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant