Shikhil Saxena

Jun 02, 2026 • 6 min read

React 19 Upgrade in WordPress

WordPress is upgrading from React 18 to React 19. This change will first ship in the Gutenberg plugin (version 23.3) and is expected to land in WordPress 7.1.

In June 2024, WordPress 6.6 shipped React 18.3, which added deprecation warnings to help developers prepare for this upgrade (see Preparation for React 19 Upgrade). Now that the migration work is complete, this post covers everything plugin and theme developers need to know.

Timeline

  • Gutenberg plugin: React 19 will be merged into the Gutenberg trunk branch after the 7.0 release. It will ship in a Gutenberg release shortly after, with npm packages following.

  • WordPress Core: The upgrade is targeted for WordPress 7.1, providing a full release cycle for testing.

We encourage developers to begin testing as early as possible once the Gutenberg plugin release with React 19 is available.

Removed APIs

The following functions have been removed from React 19 after a long deprecation period. In WordPress, these were deprecated since WordPress 6.2 (March 2023):

render and hydrate

ReactDOM.render() and ReactDOM.hydrate() have been removed. Use createRoot() and hydrateRoot() instead:

// Before (deprecated).

import { render } from '@wordpress/element';

render( <App />, document.getElementById( 'root' ) );

 

// After.

import { createRoot } from '@wordpress/element';

const root = createRoot( document.getElementById( 'root' ) );

root.render( <App /> );

unmountComponentAtNode

ReactDOM.unmountComponentAtNode() has been removed. Use root.unmount() instead:

// Before (deprecated).

import { unmountComponentAtNode } from '@wordpress/element';

unmountComponentAtNode( document.getElementById( 'root' ) );

 

// After.

root.unmount();

findDOMNode

ReactDOM.findDOMNode() has been removed from React 19. However, @wordpress/element continues to export a polyfill for findDOMNode to ease the transition. Note that the react-dom script itself will no longer include this function — only the wp-element script will provide it.

We recommend migrating away from findDOMNode by using refs instead, as it was already discouraged in earlier versions of React.

defaultProps for function components

As noted in the React 18.3 dev note, defaultProps for function components is no longer supported. Use ES6 default parameters instead:

// Before (no longer supported).

function MyComponent( { size } ) {

    return <div style={ { width: size } } />;

}

MyComponent.defaultProps = { size: 100 };

 

// After.

function MyComponent( { size = 100 } ) {

    return <div style={ { width: size } } />;

}

Changed behavior

The inert attribute is now a boolean

The HTML inert attribute has changed from a string type to a boolean in React 19. If your code sets inert as a string (inert="true" or inert=""), update it to use a boolean value:

// Before.

<div inert="" />

<div inert="true" />

 

// After.

<div inert />

<div inert={ true } />

Ref callbacks can return cleanup functions

Ref callbacks can now optionally return a cleanup function, similar to useEffect. React will call the cleanup function when the element is removed from the DOM. This is a powerful new pattern that reduces the need for separate useEffect hooks to manage DOM element lifecycle.

// New pattern: ref callback with cleanup.

<div ref={ ( node ) => {

    if ( node ) {

        const handler = () => { /* ... */ };

        node.addEventListener( 'scroll', handler );

        return () => node.removeEventListener( 'scroll', handler );

    }

} } />

Important: If your existing ref callbacks return a value (e.g., returning something other than undefined), React 19 may interpret that as a cleanup function. Make sure your ref callbacks either return undefined or a valid cleanup function.

forwardRef is no longer needed

In React 19, function components can accept ref as a regular prop. forwardRef still works but is considered deprecated and will be removed in a future version.

// Before.

const MyInput = forwardRef( ( props, ref ) => {

    return <input ref={ ref } { ...props } />;

} );

 

// After.

function MyInput( { ref, ...props } ) {

    return <input ref={ ref } { ...props } />;

}

New APIs available

React 19 introduces several new APIs, now available through @wordpress/element:

  • use — Read a resource (Promise or Context) during render.

  • useActionState — Manage state based on form action results.

  • useOptimistic — Show optimistic UI state while an async action is in progress.

  • useFormStatus — Access the status of a parent form.

From React 19.2:

  • Activity — Hide and show parts of the UI while preserving their state and DOM.

  • useEffectEvent — Extract non-reactive logic from effects.

TypeScript type changes

React 19 includes a major update to its TypeScript types. Developers using TypeScript should be aware of the following:

Ref types

The MutableRefObject type is deprecated. The type inference rules for useRef and RefObject have changed, especially regarding declaring values as “T or null“. Update your code to use the new RefObject type.

ReactElement props type changed from any to unknown

The ReactElement type now types its props as unknown instead of any. This reveals previously unsound access to props that was silently allowed before. This manifests especially in cloneElement calls, where reading or setting props on a cloned element now requires the element type to explicitly support those props.

HTML element prop conflicts

Many WordPress components extend native HTML elements, accepting all props that (for example) a <div> accepts plus custom props. If the HTML standard adds a new prop to <div> with a name that conflicts with a custom prop, TypeScript may report errors. Developers may need to resolve naming conflicts (as was the case with onToggle in this migration).

For a comprehensive list of TypeScript changes, see the React 19 typechecking guide.

How to test your plugin

  1. Install the latest Gutenberg plugin that includes React 19 (version TBD).

  2. Enable development mode (SCRIPT_DEBUG set to true in wp-config.php) to get detailed warnings and errors.

  3. Test all major features of your plugin — especially any code that uses the removed APIs (render, hydrate, unmountComponentAtNode, findDOMNode, defaultProps for function components).

  4. Check the browser console for React warnings and errors. React 19 has improved error reporting and may surface issues that were previously silent.

  5. Test iframe interactions if your plugin renders content inside iframes or communicates between frames, as there have been subtle behavior changes in this area.

Further reading

Call for testing

We encourage all plugin and theme developers to test their code with the Gutenberg plugin as soon as the React 19 release is available. Early testing helps us identify and fix issues before the upgrade reaches WordPress Core. If you encounter bugs, please report them on the Gutenberg GitHub repository.

Join Shikhil on Peerlist!

Join amazing folks like Shikhil and thousands of other builders on Peerlist.

peerlist.io/

It’s available... this username is available! 😃

Claim your username before it's too late!

This username is already taken, you’re a little late.😐

0

1

0