Skip to content

Upgrade React from 17 to 19#10295

Open
ranm8 wants to merge 3 commits intomasterfrom
ui-react-19-upgrade
Open

Upgrade React from 17 to 19#10295
ranm8 wants to merge 3 commits intomasterfrom
ui-react-19-upgrade

Conversation

@ranm8
Copy link
Copy Markdown
Member

@ranm8 ranm8 commented Apr 14, 2026

Summary

  • Upgrade React and React DOM from 17.0.2 to 19.1.0
  • Migrate from legacy ReactDOM.render() to the new createRoot API (react-dom/client)
  • Update related dependencies: @types/react 19, @types/react-dom 19, @testing-library/react 14, @monaco-editor/react 4.7, @apollo/client 3.12, monaco-editor 0.52, react-animate-height 3.x, react-test-renderer 19
  • Remove react-dom/server alias from webpack/rspack configs (no longer needed)
  • Remove @teambit/react.rendering.ssr dependency

Test plan

  • Run bit start and verify the UI loads correctly
  • Test component compositions render properly in preview
  • Test component docs render properly in preview
  • Verify no console warnings about deprecated React APIs
  • Run bit test to check unit tests pass

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings April 14, 2026 23:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Upgrades the workspace to React/React DOM 19 and modernizes mounting logic to the createRoot() API, alongside related dependency updates and build config tweaks.

Changes:

  • Upgrade React/ReactDOM (and related typings/testing libs) and adjust workspace dependency policy.
  • Migrate legacy ReactDOM.render() entrypoints to createRoot(...).render(...).
  • Remove react-dom/server aliases from webpack/rspack configs and adjust SSR-related dependencies/mappings.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
workspace.jsonc Updates React + ecosystem versions, adjusts dependency policy (including removing @teambit/react.rendering.ssr).
scopes/ui-foundation/ui/rspack/rspack.common.ts Removes react-dom/server alias from rspack resolve aliases.
scopes/react/ui/docs-app/docs.app-root.tsx Migrates docs preview mounting to createRoot().render().
scopes/react/ui/compositions-app/compositions.app-root.tsx Migrates compositions preview mounting to createRoot().render().
scopes/react/react/webpack/webpack.config.base.ts Removes react-dom/server alias from webpack resolve aliases.
scopes/docs/docs/docs-store.tsx Migrates docs store rendering to createRoot().render().
.bitmap Adds a rendering/ssr component mapping entry.
Comments suppressed due to low confidence (2)

scopes/ui-foundation/ui/rspack/rspack.common.ts:33

  • react-dom/server is still imported in the codebase (e.g. scopes/harmony/graphql/render-lifecycle.tsx, components/ui/pages/static-error/render-page.tsx). Removing the explicit alias here can reintroduce the historical “webpack is not bundling react-dom/server” issue noted in render-lifecycle.tsx. If this alias truly isn’t needed anymore, consider updating/removing that comment and validating SSR bundling; otherwise keep the alias (or scope it to SSR builds only).
export function resolveAlias(opts?: { profile?: boolean }): Record<string, string | false> {
  return {
    'react/jsx-runtime': require.resolve('react/jsx-runtime'),
    react: require.resolve('react'),
    'react-dom': require.resolve('react-dom'),
    ...(opts?.profile && {
      'react-dom$': 'react-dom/profiling',
      'scheduler/tracing': 'scheduler/tracing-profiling',
    }),

scopes/react/react/webpack/webpack.config.base.ts:83

  • Same concern as the rspack alias removal: there are still SSR usages of react-dom/server, and an existing comment indicates bundling issues without an explicit alias. Please ensure SSR builds still bundle react-dom/server correctly after removing this alias (or keep/relocate the alias to the SSR webpack configuration).
      extensions: moduleFileExtensions.map((ext) => `.${ext}`),

      alias: {
        'react/jsx-dev-runtime': require.resolve('react/jsx-dev-runtime'),
        'react/jsx-runtime': require.resolve('react/jsx-runtime'),
        // Allows for better profiling with ReactDevTools
        ...(isEnvProductionProfile && {
          'react-dom$': 'react-dom/profiling',
          'scheduler/tracing': 'scheduler/tracing-profiling',
        }),
      },

Comment thread workspace.jsonc
"execa": "2.1.0",
"expose-loader": "3.1.0",
"express": "4.21.2",
"express": "^4.21.0",
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most dependencies in this policy are pinned to exact versions, but express was changed to a caret range (and effectively downgraded from 4.21.2 to ^4.21.0). This reduces reproducibility and can introduce untested minor/patch behavior changes. Consider keeping the exact version pin unless there’s a specific need for a range.

Suggested change
"express": "^4.21.0",
"express": "4.21.2",

Copilot uses AI. Check for mistakes.
Comment thread .bitmap
Comment on lines +7 to +13
let root;

function DocsRoot({ componentId, docs, compositions, context }: DocsRootProps) {
ReactDOM.render(
<DocsApp componentId={componentId} docs={docs} compositions={compositions} context={context} />,
document.getElementById('root')
);
if (!root) {
root = createRoot(document.getElementById('root')!);
}
root.render(<DocsApp componentId={componentId} docs={docs} compositions={compositions} context={context} />);
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

root is currently an untyped module-level variable and the container is assumed to exist via getElementById('root')!. For better safety/maintainability, consider typing this as Root | undefined (import type Root from react-dom/client) and handling the case where #root is missing (throw a clear error). Also consider recreating the root if the container element changes between calls (e.g. during preview re-mounts).

Copilot uses AI. Check for mistakes.
Comment thread workspace.jsonc
@@ -314,7 +314,6 @@
"@teambit/react.instructions.react.adding-compositions": "0.0.7",
"@teambit/react.instructions.react.adding-tests": "0.0.6",
"@teambit/react.jest.react-jest": "^1.0.37",
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@teambit/react.rendering.ssr was removed from the workspace dependency policy, but the codebase still imports it in multiple places (e.g. scopes/react/react/apps/web/ssr/ssr-express.ts, scopes/ui-foundation/ui/ssr-middleware/ssr-middleware.ts, scopes/ui-foundation/ui/ui.ui.runtime.tsx). Unless it’s being provided as a local component, this will likely break installs/builds in pnpm/Bit capsules. Consider re-adding it here or migrating those imports to the replacement SSR package/component as part of this PR.

Suggested change
"@teambit/react.jest.react-jest": "^1.0.37",
"@teambit/react.jest.react-jest": "^1.0.37",
"@teambit/react.rendering.ssr": "^1.0.0",

Copilot uses AI. Check for mistakes.
Comment thread workspace.jsonc
Comment on lines 678 to +682
"core-js": "^3.10.0",
"graphql": "15.8.0",
"mz": "2.7.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react": "19.1.0",
"react-dom": "19.1.0",
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React/ReactDOM peers are updated to 19.1.0 here, but the SSR app build policy in scopes/react/react/apps/web/react.application.ts#getSsrPolicy() is still pinning react/react-dom to 17.0.2. That will produce SSR bundles running a different React major than the rest of the workspace. Update the SSR policy to React 19 (or document why SSR must remain on 17).

Copilot uses AI. Check for mistakes.
Comment thread workspace.jsonc
"@types/eslint": "8.56.6",
"@types/eventsource": "^1.1.15",
"@types/express": "4.17.21",
"@types/express": "^4.17.21",
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@types/express was changed from an exact version to a caret range, while most @types/* dependencies in this file are pinned. This can lead to unexpected type changes on reinstall/CI. Consider pinning an exact version (or apply the same range strategy consistently across types).

Suggested change
"@types/express": "^4.17.21",
"@types/express": "4.17.21",

Copilot uses AI. Check for mistakes.
Comment on lines +7 to +16
let root;

/**
* mounts compositions into the DOM in the component preview.
*/
export default (Composition: React.ComponentType, previewContext: RenderingContext) => {
ReactDOM.render(
<CompositionsApp Composition={Composition} previewContext={previewContext} />,
document.getElementById('root')
);
if (!root) {
root = createRoot(document.getElementById('root')!);
}
root.render(<CompositionsApp Composition={Composition} previewContext={previewContext} />);
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern as docs-app: root is untyped and getElementById('root')! assumes the container exists forever. Typing root as Root | undefined, validating the container, and recreating the root if the container changes will make preview mounts more robust.

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +11
let root;

export function addDocs(docs: any[]) {
const Doc = docs[0];
ReactDOM.render(<Doc />, document.getElementById('root'));
if (!root) {
root = createRoot(document.getElementById('root')!);
}
root.render(<Doc />);
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

root is kept as a module-level variable without a type and the #root element is asserted with !. Consider typing the root (Root | undefined) and handling a missing container with a clearer error to avoid hard-to-debug runtime crashes when the docs store is used outside the expected DOM environment.

Copilot uses AI. Check for mistakes.
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.

2 participants