Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions src/libs/DebugDashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,27 @@
*/

import React, { Suspense, lazy } from 'react';
import { createRoot } from 'react-dom/client';
import * as ReactDOM from 'react-dom';
import { subscribe } from 'subscribe-ui-event';

// react-dom/client only exists in React 18+, fall back to the legacy API for React 16/17
let createRoot = null;
try {
// eslint-disable-next-line global-require
({ createRoot } = require('react-dom/client'));
} catch {
createRoot = null;
}

/* eslint-disable react/no-deprecated */
const legacyRoot = (container) => ({
render: (...args) => {
ReactDOM.render(...args);
},
unmount: () => ReactDOM.unmountComponentAtNode(container)
});
/* eslint-enable react/no-deprecated */

// Dashboard only used in client side, could safely defered load
const Dashboard = lazy(() => import(/* webpackChunkName: "i13n-debug-dashboard" */ '../components/debug/Dashboard'));

Expand Down Expand Up @@ -112,7 +130,7 @@ const DebugDashboard = function DebugDashboard(i13nNode) {
});
};

this.root = createRoot(container);
this.root = createRoot ? createRoot(container) : legacyRoot(container);
this.root.render(
React.createElement(
Suspense,
Expand Down
29 changes: 29 additions & 0 deletions src/libs/tests/DebugDashboard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,33 @@ describe('clickHandler', () => {
expect(document.getElementById('i13n-debug-0')).toBeDefined();
debugDashboard.destroy();
});

it('should fall back to legacy react-dom api when react-dom/client is unavailable', () => {
const render = jest.fn((element, container, callback) => callback());
const unmountComponentAtNode = jest.fn();

jest.isolateModules(() => {
jest.doMock('react-dom/client', () => {
throw new Error("Cannot find module 'react-dom/client'");
});
jest.doMock('react-dom', () => ({ render, unmountComponentAtNode }));

/* eslint-disable global-require */
const LegacyDebugDashboard = require('../DebugDashboard').default;
const LegacyI13nNode = require('../../core/I13nNode').default;
/* eslint-enable global-require */

const i13nNode = new LegacyI13nNode(null, {});
i13nNode.setDOMNode(document.body.appendChild(document.createElement('div')));
const debugDashboard = new LegacyDebugDashboard(i13nNode);
const { container } = debugDashboard;
expect(render).toHaveBeenCalledWith(expect.anything(), container, expect.any(Function));

debugDashboard.destroy();
expect(unmountComponentAtNode).toHaveBeenCalledWith(container);
});

jest.dontMock('react-dom/client');
jest.dontMock('react-dom');
});
});
Loading