diff --git a/e2e/react/src/react.test.ts b/e2e/react/src/react.test.ts index 96bd03e871c6b..2130b0ecfd166 100644 --- a/e2e/react/src/react.test.ts +++ b/e2e/react/src/react.test.ts @@ -87,29 +87,10 @@ describe('React Applications', () => { const appName = uniq('app'); const libName = uniq('lib'); - runCLI(`generate @nrwl/react:app ${appName} --no-interactive`); - runCLI(`generate @nrwl/react:lib ${libName} --no-interactive`); + runCLI(`generate @nrwl/react:app ${appName} --no-interactive --js`); + runCLI(`generate @nrwl/react:lib ${libName} --no-interactive --js`); - renameFile(`apps/${appName}/src/main.tsx`, `apps/${appName}/src/main.jsx`); - renameFile( - `apps/${appName}/src/app/app.tsx`, - `apps/${appName}/src/app/app.jsx` - ); - renameFile( - `apps/${appName}/src/app/app.spec.tsx`, - `apps/${appName}/src/app/app.spec.jsx` - ); - renameFile( - `apps/${appName}/src/polyfills.ts`, - `apps/${appName}/src/polyfills.js` - ); - updateProjectConfig(appName, (config) => { - config.targets.build.options.main = `apps/${appName}/src/main.jsx`; - config.targets.build.options.polyfills = `apps/${appName}/src/polyfills.js`; - return config; - }); - - const mainPath = `apps/${appName}/src/main.jsx`; + const mainPath = `apps/${appName}/src/main.js`; updateFile( mainPath, `import '@${proj}/${libName}';\n${readFile(mainPath)}` diff --git a/packages/react/migrations.json b/packages/react/migrations.json index 3378935fc04d2..d3a844f86f5af 100644 --- a/packages/react/migrations.json +++ b/packages/react/migrations.json @@ -287,6 +287,43 @@ "alwaysAddToPackageJson": false } } + }, + "13.10.1": { + "version": "13.10.1-beta.1", + "packages": { + "@types/react": { + "version": "18.0.0", + "alwaysAddToPackageJson": false + }, + "@types/react-dom": { + "version": "18.0.0", + "alwaysAddToPackageJson": false + }, + "@types/styled-components": { + "version": "5.1.25", + "alwaysAddToPackageJson": false + }, + "@emotion/react": { + "version": "11.9.0", + "alwaysAddToPackageJson": false + }, + "@testing-library/react": { + "version": "13.0.0", + "alwaysAddToPackageJson": false + }, + "@reduxjs/toolkit": { + "version": "1.8.1", + "alwaysAddToPackageJson": false + }, + "react-redux": { + "version": "7.2.8", + "alwaysAddToPackageJson": false + }, + "eslint-plugin-import": { + "version": "2.26.0", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/react/src/generators/application/files/common/src/main.tsx__tmpl__ b/packages/react/src/generators/application/files/common/src/main.tsx__tmpl__ index 564a677ba4144..53c4e73820979 100644 --- a/packages/react/src/generators/application/files/common/src/main.tsx__tmpl__ +++ b/packages/react/src/generators/application/files/common/src/main.tsx__tmpl__ @@ -1,7 +1,10 @@ <% if (strict) { %>import { StrictMode } from 'react';<% } %> -import * as ReactDOM from 'react-dom'; +import * as ReactDOMClient from 'react-dom/client'; <% if (routing) { %>import { BrowserRouter } from 'react-router-dom';<% } %> import App from './app/<%= fileName %>'; -ReactDOM.render(<% if (strict) { %><% } %><% if (routing) { %><% } %><% if (routing) { %><% } %><% if (strict) { %><% } %>, document.getElementById('root')); +const root = ReactDOMClient.createRoot(document.getElementById('root') as HTMLElement); +root.render( +<% if (strict) { %><% } %><% if (routing) { %><% } %><% if (routing) { %><% } %><% if (strict) { %><% } %> +); diff --git a/packages/react/src/utils/ast-utils.spec.ts b/packages/react/src/utils/ast-utils.spec.ts index 555a36be68b53..141278de04fcd 100644 --- a/packages/react/src/utils/ast-utils.spec.ts +++ b/packages/react/src/utils/ast-utils.spec.ts @@ -219,7 +219,7 @@ describe('findMainRenderStatement', () => { tree = createTreeWithEmptyWorkspace(); }); - it('should return render(...)', () => { + it('should return ReactDOM.render(...)', () => { const sourceCode = ` import React from 'react'; import ReactDOM from 'react-dom'; @@ -237,6 +237,25 @@ ReactDOM.render(
, document.getElementById('root')); expect(node).toBeTruthy(); }); + it('should return root.render(...)', () => { + const sourceCode = ` +import React from 'react'; +import ReactDOMClient from 'react-dom/client'; +const root = ReactDOM.createRoot(document.getElementById('root')); +root.render(
); + `; + tree.write('/main.tsx', sourceCode); + const source = ts.createSourceFile( + '/main.tsx', + sourceCode, + ts.ScriptTarget.Latest, + true + ); + + const node = utils.findMainRenderStatement(source); + expect(node).toBeTruthy(); + }); + it('should return render(...)', () => { const sourceCode = ` import React from 'react'; diff --git a/packages/react/src/utils/ast-utils.ts b/packages/react/src/utils/ast-utils.ts index 12452c4c7254d..4356217adb361 100644 --- a/packages/react/src/utils/ast-utils.ts +++ b/packages/react/src/utils/ast-utils.ts @@ -43,6 +43,7 @@ export function findMainRenderStatement( for (const expr of calls) { const inner = expr.expression; + // React 17 and below if ( ts.isPropertyAccessExpression(inner) && /ReactDOM/i.test(inner.expression.getText()) && @@ -50,6 +51,15 @@ export function findMainRenderStatement( ) { return expr; } + + // React 18 + if ( + ts.isPropertyAccessExpression(inner) && + /root/.test(inner.expression.getText()) && + inner.name.getText() === 'render' + ) { + return expr; + } } // 2. Try to find render from 'react-dom'. @@ -358,7 +368,7 @@ export function addReduxStoreToMain( ): StringChange[] { const renderStmt = findMainRenderStatement(source); if (!renderStmt) { - logger.warn(`Could not find ReactDOM.render in ${sourcePath}`); + logger.warn(`Could not find render(...) in ${sourcePath}`); return []; } const jsx = renderStmt.arguments[0]; diff --git a/packages/react/src/utils/versions.ts b/packages/react/src/utils/versions.ts index 099a99e8b54ed..2c032235862eb 100755 --- a/packages/react/src/utils/versions.ts +++ b/packages/react/src/utils/versions.ts @@ -3,15 +3,15 @@ export const nxVersion = '*'; export const reactVersion = '18.0.0'; export const reactDomVersion = '18.0.0'; export const reactIsVersion = '18.0.0'; -export const typesReactVersion = '17.0.43'; -export const typesReactDomVersion = '17.0.14'; +export const typesReactVersion = '18.0.0'; +export const typesReactDomVersion = '18.0.0'; export const typesReactIsVersion = '17.0.3'; export const styledComponentsVersion = '5.3.5'; -export const typesStyledComponentsVersion = '5.1.24'; +export const typesStyledComponentsVersion = '5.1.25'; export const emotionStyledVersion = '11.8.1'; -export const emotionReactVersion = '11.8.2'; +export const emotionReactVersion = '11.9.0'; export const emotionBabelPlugin = '11.7.2'; export const styledJsxVersion = '5.0.2'; @@ -19,14 +19,14 @@ export const styledJsxVersion = '5.0.2'; export const reactRouterDomVersion = '5.3.0'; export const typesReactRouterDomVersion = '5.3.3'; -export const testingLibraryReactVersion = '12.1.4'; +export const testingLibraryReactVersion = '13.0.0'; export const testingLibraryReactHooksVersion = '7.0.2'; -export const reduxjsToolkitVersion = '1.8.0'; -export const reactReduxVersion = '7.2.6'; +export const reduxjsToolkitVersion = '1.8.1'; +export const reactReduxVersion = '7.2.8'; export const reactTestRendererVersion = '18.0.0'; -export const eslintPluginImportVersion = '2.25.4'; +export const eslintPluginImportVersion = '2.26.0'; export const eslintPluginJsxA11yVersion = '6.5.1'; export const eslintPluginReactVersion = '7.29.4'; export const eslintPluginReactHooksVersion = '4.4.0';