Merge pull request #20596 from backstage/rugvip/react-18-compat

dev-utils,techdocs: add conditional support for React 18
This commit is contained in:
Patrik Oldsberg
2023-10-13 16:40:17 +02:00
committed by GitHub
13 changed files with 113 additions and 25 deletions
@@ -21,8 +21,8 @@ import {
} from '@backstage/integration';
import FeedbackOutlinedIcon from '@material-ui/icons/FeedbackOutlined';
import React from 'react';
import ReactDOM from 'react-dom';
import parseGitUrl from 'git-url-parse';
import { renderReactElement } from './renderReactElement';
// requires repo
export const addGitFeedbackLink = (
@@ -75,7 +75,7 @@ export const addGitFeedbackLink = (
default:
return dom;
}
ReactDOM.render(React.createElement(FeedbackOutlinedIcon), feedbackLink);
renderReactElement(React.createElement(FeedbackOutlinedIcon), feedbackLink);
feedbackLink.style.paddingLeft = '5px';
feedbackLink.title = 'Leave feedback for this page';
feedbackLink.id = 'git-feedback-link';
@@ -17,7 +17,7 @@
import type { Transformer } from './transformer';
import MenuIcon from '@material-ui/icons/Menu';
import React from 'react';
import ReactDOM from 'react-dom';
import { renderReactElement } from './renderReactElement';
export const addSidebarToggle = (): Transformer => {
return dom => {
@@ -33,7 +33,7 @@ export const addSidebarToggle = (): Transformer => {
}
const toggleSidebar = mkdocsToggleSidebar.cloneNode() as HTMLLabelElement;
ReactDOM.render(React.createElement(MenuIcon), toggleSidebar);
renderReactElement(React.createElement(MenuIcon), toggleSidebar);
toggleSidebar.id = 'toggle-sidebar';
toggleSidebar.title = 'Toggle Sidebar';
toggleSidebar.classList.add('md-content__button');
@@ -17,7 +17,7 @@
import { createTestShadowDom } from '../../test-utils';
import { copyToClipboard } from './copyToClipboard';
import { lightTheme } from '@backstage/theme';
import { waitFor } from '@testing-library/react';
import { act, waitFor } from '@testing-library/react';
import useCopyToClipboard from 'react-use/lib/useCopyToClipboard';
const clipboardSpy = jest.fn();
@@ -43,8 +43,11 @@ describe('copyToClipboard', () => {
spy.mockReturnValue([{}, copy]);
const expectedClipboard = 'function foo() {return "bar";}';
const shadowDom = await createTestShadowDom(
`
let shadowDom: ShadowRoot;
await act(async () => {
shadowDom = await createTestShadowDom(
`
<!DOCTYPE html>
<html>
<body>
@@ -52,13 +55,20 @@ describe('copyToClipboard', () => {
</body>
</html>
`,
{
preTransformers: [],
postTransformers: [copyToClipboard(lightTheme)],
},
);
{
preTransformers: [],
postTransformers: [copyToClipboard(lightTheme)],
},
);
});
shadowDom.querySelector('button')?.click();
await waitFor(() => {
expect(shadowDom.querySelector('button')).not.toBe(null);
});
await act(async () => {
shadowDom.querySelector('button')!.click();
});
await waitFor(() => {
const tooltip = document.querySelector('[role="tooltip"]');
@@ -15,7 +15,7 @@
*/
import React, { useState, useCallback } from 'react';
import ReactDom from 'react-dom';
import { renderReactElement } from './renderReactElement';
import {
withStyles,
Theme,
@@ -91,7 +91,7 @@ export const copyToClipboard = (theme: Theme): Transformer => {
const text = code.textContent || '';
const container = document.createElement('div');
code?.parentElement?.prepend(container);
ReactDom.render(
renderReactElement(
<ThemeProvider theme={theme}>
<CopyToClipboardButton text={text} />
</ThemeProvider>,
@@ -0,0 +1,34 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let ReactDOM:
| typeof import('react-dom')
// TODO: replace with import('react-dom/client') when repo is migrated to 18
| { createRoot(el: HTMLElement): { render(el: JSX.Element): void } };
if (process.env.HAS_REACT_DOM_CLIENT) {
ReactDOM = require('react-dom/client');
} else {
ReactDOM = require('react-dom');
}
/** @internal */
export function renderReactElement(element: JSX.Element, root: HTMLElement) {
if ('createRoot' in ReactDOM) {
ReactDOM.createRoot(root).render(element);
} else {
ReactDOM.render(element, root);
}
}