diff --git a/lib/client-assets.php b/lib/client-assets.php
index 13884f90fb3ea5..ef8ce0383a4726 100644
--- a/lib/client-assets.php
+++ b/lib/client-assets.php
@@ -590,6 +590,14 @@ function gutenberg_register_vendor_scripts( $scripts ) {
array( 'react' ),
'18'
);
+
+ gutenberg_override_script(
+ $scripts,
+ 'react-jsx-runtime',
+ gutenberg_url( 'build/react-jsx-runtime/index.min.js' ),
+ array( 'react' ),
+ '18'
+ );
}
add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );
diff --git a/package-lock.json b/package-lock.json
index a8dbbedaf11cbf..006be0a65641af 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -53162,7 +53162,6 @@
"@babel/preset-env": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@babel/runtime": "^7.16.0",
- "@wordpress/babel-plugin-import-jsx-pragma": "file:../babel-plugin-import-jsx-pragma",
"@wordpress/browserslist-config": "file:../browserslist-config",
"@wordpress/warning": "file:../warning",
"browserslist": "^4.21.10",
@@ -68508,7 +68507,6 @@
"@babel/preset-env": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@babel/runtime": "^7.16.0",
- "@wordpress/babel-plugin-import-jsx-pragma": "file:../babel-plugin-import-jsx-pragma",
"@wordpress/browserslist-config": "file:../browserslist-config",
"@wordpress/warning": "file:../warning",
"browserslist": "^4.21.10",
diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md
index 5735008dd472dc..15ced9c9dde12c 100644
--- a/packages/babel-preset-default/CHANGELOG.md
+++ b/packages/babel-preset-default/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Breaking Changes
+
+- Use React's automatic runtime to transform JSX ([#61692](https://github.com/WordPress/gutenberg/pull/61692)).
+
## 7.42.0 (2024-05-16)
## 7.41.0 (2024-05-02)
diff --git a/packages/babel-preset-default/index.js b/packages/babel-preset-default/index.js
index 40f7c31bb3c25b..45ec6473be3cbc 100644
--- a/packages/babel-preset-default/index.js
+++ b/packages/babel-preset-default/index.js
@@ -75,21 +75,10 @@ module.exports = ( api ) => {
],
plugins: [
require.resolve( '@wordpress/warning/babel-plugin' ),
- [
- require.resolve( '@wordpress/babel-plugin-import-jsx-pragma' ),
- {
- scopeVariable: 'createElement',
- scopeVariableFrag: 'Fragment',
- source: 'react',
- isDefault: false,
- },
- ],
[
require.resolve( '@babel/plugin-transform-react-jsx' ),
{
- pragma: 'createElement',
- pragmaFrag: 'Fragment',
- useSpread: true,
+ runtime: 'automatic',
},
],
maybeGetPluginTransformRuntime(),
diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json
index 4b12101565b45c..438cce0f47b96b 100644
--- a/packages/babel-preset-default/package.json
+++ b/packages/babel-preset-default/package.json
@@ -35,7 +35,6 @@
"@babel/preset-env": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@babel/runtime": "^7.16.0",
- "@wordpress/babel-plugin-import-jsx-pragma": "file:../babel-plugin-import-jsx-pragma",
"@wordpress/browserslist-config": "file:../browserslist-config",
"@wordpress/warning": "file:../warning",
"browserslist": "^4.21.10",
diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 393c9f7e0797f1..5579894741c7c3 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Internal
+
+- Remove usage of deprecated spreading of `key` prop in JSX ([#61692](https://github.com/WordPress/gutenberg/pull/61692)).
+
## 27.6.0 (2024-05-16)
### Internal
diff --git a/packages/components/src/custom-select-control/index.js b/packages/components/src/custom-select-control/index.js
index 46bc4f4d9a4fb1..24b3d8bdb9bd3f 100644
--- a/packages/components/src/custom-select-control/index.js
+++ b/packages/components/src/custom-select-control/index.js
@@ -187,10 +187,10 @@ export default function CustomSelectControl( props ) {
items.map( ( item, index ) => (
// eslint-disable-next-line react/jsx-key
= maxLength )
diff --git a/packages/dependency-extraction-webpack-plugin/lib/util.js b/packages/dependency-extraction-webpack-plugin/lib/util.js
index 92fdcff11612ea..907f1db782a9f6 100644
--- a/packages/dependency-extraction-webpack-plugin/lib/util.js
+++ b/packages/dependency-extraction-webpack-plugin/lib/util.js
@@ -42,6 +42,9 @@ function defaultRequestToExternal( request ) {
case 'react-dom':
return 'ReactDOM';
+
+ case 'react/jsx-runtime':
+ return 'ReactJSXRuntime';
}
if ( request.includes( 'react-refresh/runtime' ) ) {
@@ -117,6 +120,9 @@ function defaultRequestToHandle( request ) {
case 'lodash-es':
return 'lodash';
+
+ case 'react/jsx-runtime':
+ return 'react-jsx-runtime';
}
if ( request.includes( 'react-refresh/runtime' ) ) {
diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx
index 07328df8af210b..cfe6adc468a011 100644
--- a/packages/interactivity/src/directives.tsx
+++ b/packages/interactivity/src/directives.tsx
@@ -1,8 +1,6 @@
// eslint-disable-next-line eslint-comments/disable-enable-pair
/* eslint-disable react-hooks/exhaustive-deps */
-/* @jsx createElement */
-
/**
* External dependencies
*/
@@ -233,6 +231,7 @@ export default () => {
// data-wp-context
directive(
'context',
+ // @ts-ignore-next-line
( {
directives: { context },
props: { children },
@@ -262,7 +261,7 @@ export default () => {
return proxifyContext( currentValue.current, inheritedValue );
}, [ defaultEntry, inheritedValue ] );
- return { children };
+ return createElement( Provider, { value: contextStack }, children );
},
{ priority: 5 }
);
@@ -483,12 +482,10 @@ export default () => {
} ) => {
// Preserve the initial inner HTML.
const cached = useMemo( () => innerHTML, [] );
- return (
-
- );
+ return createElement( Type, {
+ dangerouslySetInnerHTML: { __html: cached },
+ ...rest,
+ } );
}
);
@@ -551,10 +548,10 @@ export default () => {
? getEvaluate( { scope } )( eachKey[ 0 ] )
: item;
- return (
-
- { element.props.content }
-
+ return createElement(
+ Provider,
+ { value: mergedContext, key },
+ element.props.content
);
} );
},
diff --git a/packages/interactivity/src/hooks.tsx b/packages/interactivity/src/hooks.tsx
index 2dfc08a43f6fa8..91876e627e1a3b 100644
--- a/packages/interactivity/src/hooks.tsx
+++ b/packages/interactivity/src/hooks.tsx
@@ -1,5 +1,3 @@
-/* @jsx createElement */
-
// eslint-disable-next-line eslint-comments/disable-enable-pair
/* eslint-disable react-hooks/exhaustive-deps */
@@ -352,17 +350,15 @@ const Directives = ( {
// Recursively render the wrapper for the next priority level.
const children =
- nextPriorityLevels.length > 0 ? (
-
- ) : (
- element
- );
+ nextPriorityLevels.length > 0
+ ? createElement( Directives, {
+ directives,
+ priorityLevels: nextPriorityLevels,
+ element,
+ originalProps,
+ previousScope: scope,
+ } )
+ : element;
const props = { ...originalProps, children };
const directiveArgs = {
diff --git a/packages/react-native-editor/babel.config.js b/packages/react-native-editor/babel.config.js
index 27a43df36e98b3..ae6fc3cec3ebe8 100644
--- a/packages/react-native-editor/babel.config.js
+++ b/packages/react-native-editor/babel.config.js
@@ -32,24 +32,7 @@ module.exports = function ( api ) {
[
'@babel/plugin-transform-react-jsx',
{
- pragma: 'createElement',
- pragmaFrag: 'Fragment',
- },
- ],
- ],
- exclude:
- /node_modules\/(react-native|@react-native-community|@react-navigation|react-native-reanimated)/,
- },
- {
- // Auto-add `import { createElement } from 'react';` when JSX is found.
- plugins: [
- [
- '@wordpress/babel-plugin-import-jsx-pragma',
- {
- scopeVariable: 'createElement',
- scopeVariableFrag: 'Fragment',
- source: 'react',
- isDefault: false,
+ runtime: 'automatic',
},
],
],
diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md
index 8bc3319e52836c..8c5aa8c623ef09 100644
--- a/packages/scripts/CHANGELOG.md
+++ b/packages/scripts/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Breaking Changes
+
+- Use React's automatic runtime to transform JSX ([#61692](https://github.com/WordPress/gutenberg/pull/61692)).
+
## 27.9.0 (2024-05-16)
### New Features
diff --git a/test/native/babel.config.js b/test/native/babel.config.js
index d7bf10b1dfbc4b..0372e9fbd0a2de 100644
--- a/test/native/babel.config.js
+++ b/test/native/babel.config.js
@@ -22,23 +22,7 @@ module.exports = ( api ) => {
[
'@babel/plugin-transform-react-jsx',
{
- pragma: 'createElement',
- pragmaFrag: 'Fragment',
- },
- ],
- ],
- exclude: /node_modules\/react-native/,
- },
- {
- // Auto-add `import { createElement } from '@wordpress/element';` when JSX is found.
- plugins: [
- [
- '../../packages/babel-plugin-import-jsx-pragma',
- {
- scopeVariable: 'createElement',
- scopeVariableFrag: 'Fragment',
- source: '@wordpress/element',
- isDefault: false,
+ runtime: 'automatic',
},
],
],
diff --git a/tools/webpack/development.js b/tools/webpack/development.js
index 88ac4fba42f202..716adaccbc1b92 100644
--- a/tools/webpack/development.js
+++ b/tools/webpack/development.js
@@ -46,4 +46,37 @@ module.exports = [
} ),
],
},
+ {
+ ...sharedConfig,
+ mode:
+ process.env.NODE_ENV === 'production'
+ ? 'production'
+ : 'development',
+ name: 'react-jsx-runtime',
+ entry: {
+ 'react-jsx-runtime': {
+ import: 'react/jsx-runtime',
+ library: {
+ name: 'ReactJSXRuntime',
+ type: 'window',
+ },
+ },
+ },
+ plugins: [
+ new DependencyExtractionWebpackPlugin( {
+ injectPolyfill: false,
+ useDefaults: false,
+ requestToExternal: ( request ) => {
+ if ( request === 'react' ) {
+ return 'React';
+ }
+ },
+ requestToHandle: ( request ) => {
+ if ( request === 'react' ) {
+ return 'react';
+ }
+ },
+ } ),
+ ],
+ },
];