core icon indicating copy to clipboard operation
core copied to clipboard

Add Explicit Support for React 19 in compat.ts

Open arunph opened this issue 10 months ago • 1 comments

packages/bridge/bridge-react/src/provider/compat.ts

import ReactDOM from 'react-dom';
import { CreateRootOptions, Root } from '../types';

// ReactDOM.version is only available in React 16.13.0 and later
const isReact18 = ReactDOM.version?.startsWith('18');

/**
 * Creates a root for a container element compatible with both React 16 and 18
 */
export function createRoot(
  container: Element | DocumentFragment,
  options?: CreateRootOptions,
): Root {
  if (isReact18) {
    // For React 18, use the new createRoot API
    // @ts-ignore - Types will be available in React 18
    return (ReactDOM as any).createRoot(container, options);
  }

  // For React 16/17, simulate the new root API using render/unmountComponentAtNode
  return {
    render(children: React.ReactNode) {
      ReactDOM.render(children, container);
    },
    unmount() {
      ReactDOM.unmountComponentAtNode(container);
    },
  };
}

/**
 * Hydrates a container compatible with both React 16 and 18
 */
export function hydrateRoot(
  container: Element | DocumentFragment,
  initialChildren: React.ReactNode,
  options?: CreateRootOptions,
): Root {
  if (isReact18) {
    // For React 18, use the new hydrateRoot API
    // @ts-ignore - Types will be available in React 18
    return (ReactDOM as any).hydrateRoot(container, initialChildren, options);
  }

  // For React 16/17, simulate the new root API using hydrate/unmountComponentAtNode
  return {
    render(children: React.ReactNode) {
      // For the initial render, use hydrate
      if (children === initialChildren) {
        ReactDOM.hydrate(children, container);
      } else {
        // For subsequent renders, use regular render
        ReactDOM.render(children, container);
      }
    },
    unmount() {
      ReactDOM.unmountComponentAtNode(container);
    },
  };
}

Currently, compat.ts in bridge-react only checks for React 18 and falls back to the React 16/17 compatibility layer for other versions. However, React 19 introduces a breaking change where ReactDOM.createRoot must be imported from react-dom/client instead of react-dom. This is not accounted for in the existing implementation.

Expected Behavior: If React 19 is detected, ReactDOM.createRoot and ReactDOM.hydrateRoot should be properly imported from react-dom/client to avoid runtime errors.

Current Issue: The current isReact18 check does not account for React 19, which means React 19 users might experience unexpected behavior.

arunph avatar Mar 25 '25 13:03 arunph

@arunph Thank you. I will fix this.

danpeen avatar Mar 26 '25 03:03 danpeen

Stale issue message

github-actions[bot] avatar May 25 '25 15:05 github-actions[bot]