Why WordPress 7.1 Stays on React 18.3
The transition to React 19 is one of the most anticipated architectural updates for the WordPress block editor. However, WordPress core developers have officially postponed the React 19 upgrade, confirming it will not ship with WordPress 7.1. Instead, WordPress 7.1 will continue to run on React 18.3.
This decision was made after core developers briefly enabled React 19 in the Gutenberg plugin. During this integration phase, testing revealed unexpected runtime incompatibilities. These conflicts occurred not only between different plugins but also in how older and newer versions of React interact within the same execution context. To prevent widespread site breakage, the change was reverted. The core team has determined that a longer testing window is necessary to refine the compatibility layer that allows legacy plugins to run smoothly alongside modern React APIs.
The Gutenberg 23.4 Experimental Flag: How to Opt-In
To facilitate thorough ecosystem testing without destabilizing production sites, the WordPress core team introduced an experimental flag in the Gutenberg plugin. Starting with Gutenberg version 23.4, developers can manually opt-in to run their WordPress environment on React 19.
To enable this testing environment, follow these steps:
- Ensure you are running a development or staging environment (do not test this on a live production site).
- Install and activate the Gutenberg plugin (version 23.4 or higher).
- Navigate to Settings › Gutenberg in your WordPress admin dashboard.
- Click on the Gutenberg Experiments tab.
- Locate the React 19 experiment checkbox, enable it, and save your changes.
Once activated, your WordPress site will load React 19 instead of React 18.3, allowing you to observe how your custom blocks, plugins, and admin interfaces behave under the new runtime.
The Danger of Bundling react/jsx-runtime
The most common technical failure mode identified during the React 19 Gutenberg experiment is the practice of bundling react/jsx-runtime directly inside plugin JavaScript assets.
When a plugin bundles its own copy of the JSX runtime, it packages React 18-specific code inside its compiled build files. When WordPress loads, it provides its own global React 19 runtime. This creates a hybrid environment where the plugin’s bundled React 18 code attempts to pass internal data structures (such as React element objects) to the global React 19 reconciler. Because the internal architecture of React elements has changed between major versions, passing these mismatched data structures leads to immediate runtime crashes and unhandled exceptions in the browser console.
If plugin developers correctly externalize their scripts, this class of compatibility issues is entirely avoided. WordPress provides an externalized react-jsx-runtime script specifically to ensure all plugins share the same global runtime instance.
How to Correctly Externalize React Dependencies
To prevent bundling conflicts, developers must ensure that React and its associated runtimes are treated as external dependencies during the build process. If you use the standard @wordpress/scripts package, this externalization happens automatically. The build tool detects imports from react or react/jsx-runtime and maps them to the global wp.element and WordPress-provided scripts.
If you are using a custom Webpack, Rollup, or Esbuild configuration, you must explicitly configure these libraries as externals. For example, in a custom Webpack configuration, your setup should look similar to this:
module.exports = {
// ... your config
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'react/jsx-runtime': 'wpReactJSXRuntime'
}
};
By ensuring these libraries are marked as external, your compiled plugin JS file will reference the global window objects provided by WordPress core rather than packaging duplicate, outdated React code inside your plugin zip file.
Deprecated and Removed React 19 APIs
Another major source of friction is the removal of legacy React APIs. React 19 removes several features that have been deprecated for over six years. Plugins relying on these outdated patterns will fail when the React 19 upgrade is finalized.
The primary removed APIs causing issues include:
- String Refs: Using string literals for refs (e.g.,
<input ref="myInput" />) is no longer supported. Developers must transition touseRefor callback refs. - Default Props on Function Components: Defining
Component.defaultPropson function components has been deprecated and is removed in React 19. Developers should use ES6 default parameters instead. - Legacy Context: Old context APIs (such as
childContextTypesandgetChildContext) have been completely removed in favor ofReact.createContext().
Refactoring Legacy Patterns
To prepare your codebase, you must refactor these legacy patterns. Below are examples of how to transition from removed APIs to modern, React 19-compatible alternatives.
1. Replacing String Refs
Legacy (Broken in React 19):
class LegacyInput extends React.Component {
componentDidMount() {
this.refs.textInput.focus();
}
render() {
return <input ref="textInput" />;
}
}
Modern (React 19 Compatible):
import { useRef, useEffect } from '@wordpress/element';
function ModernInput() {
const textInput = useRef(null);
useEffect(() => {
if (textInput.current) {
textInput.current.focus();
}
}, []);
return <input ref={textInput} />;
}
2. Replacing defaultProps on Function Components
Legacy (Broken in React 19):
function AlertButton({ message }) {
return <button>{message}</button>;
}
AlertButton.defaultProps = {
message: 'Click me'
};
Modern (React 19 Compatible):
function AlertButton({ message = 'Click me' }) {
return <button>{message}</button>;
}
The WordPress Core Compatibility Layer
To ease the transition and prevent millions of websites from breaking overnight, WordPress core contributors are actively developing a compatibility layer. This layer acts as a polyfill system, intercepting calls to certain deprecated or removed React APIs and routing them to modern equivalents.
While this compatibility layer mitigates some of the damage caused by legacy plugins, it is not a permanent solution. Polyfills introduce minor performance overhead and cannot resolve complex issues like the mixed-runtime bundling conflicts described earlier. Developers must treat the compatibility layer as a safety net rather than a license to keep writing deprecated code.
How to Audit and Test Your Plugins
Testing your plugin for React 19 readiness requires a methodical approach. You must verify that both your block editor integrations and your custom WP Admin screens perform flawlessly without throwing errors.
Follow this testing protocol:
- Activate the Experiment: Turn on the React 19 experiment in the Gutenberg plugin settings.
- Open Developer Tools: Open your browser’s developer console (F12) and clear any existing logs.
- Exercise the UI: Navigate through every screen your plugin generates. Insert your custom blocks, modify block attributes, interact with sidebars, and save the post.
- Check the Console: Look for red error messages or yellow deprecation warnings. Pay close attention to errors referencing
react-dom,jsx-runtime, or undefined properties on React internals. - Use automated tooling: The WordPress community is currently integrating automated React 19 compatibility checks into the official Plugin Check plugin. Running your plugin through this tool will help flag deprecated APIs and improper bundling configurations automatically.
Contributing to the Gutenberg Repository
The postponement of React 19 beyond WordPress 7.1 provides a critical window of opportunity for the community. Developers are highly encouraged to report any compatibility issues, edge cases, or unexpected behaviors they discover while running the Gutenberg experiment.
When reporting issues on the Gutenberg GitHub repository, include:
- The exact version of the Gutenberg plugin you are using.
- The full stack trace of any console errors.
- A description of how your plugin bundles its JavaScript assets (e.g., webpack config details).
- Whether the issue persists when the compatibility layer is active.
By actively testing and reporting these bugs now, you help core developers fine-tune the compatibility layer, ensuring a stable and seamless transition when React 19 eventually lands in WordPress core.</
Frequently asked questions
Will WordPress 7.1 ship with React 19?
No. WordPress 7.1 will continue to use React 18.3. The React 19 upgrade has been postponed to a future release to allow more time for compatibility testing.
How can I test my WordPress site with React 19 today?
You can enable React 19 by installing the Gutenberg plugin (version 23.4 or higher) and checking the React 19 experiment box under Settings > Gutenberg > Gutenberg Experiments.
What is the main cause of plugin failure under React 19?
The most common failure is bundling 'react/jsx-runtime' directly inside the plugin's JavaScript files instead of using the externalized script provided by WordPress. This causes a conflict between React 18 and React 19 runtimes.
Which React APIs are removed in React 19?
React 19 removes legacy features that have been deprecated for years, including string refs, defaultProps on function components, and legacy context APIs.
Is there an automated tool to check my plugin for React 19 compatibility?
Yes, work is underway to integrate automatic detection of these React 19 compatibility issues directly into the official WordPress 'Plugin Check' plugin.
Primary reference: Review the original announcement for exact release details. This article is an independent explanation and does not reproduce the source text.
