Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix:react 17 报错问题 (#216) #217

Merged
merged 13 commits into from Apr 23, 2022
5 changes: 2 additions & 3 deletions README.md
Expand Up @@ -28,14 +28,13 @@ import Button from '@uiw/react-button';
import CodePreview from '@uiw/react-code-preview';

const code = `import Button from '@uiw/react-button';
import ReactDOMClient from 'react-dom/client';
import ReactDOM from 'react-dom/client';

ReactDOM.render(
ReactDOM.createRoot(_mount_).render(
<div>
<Button type="primary">主要按钮</Button>
<Button type="success">成功按钮</Button>
</div>,
_mount_
);`;

export default function App() {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -102,4 +102,4 @@
"last 1 safari version"
]
}
}
}
2 changes: 1 addition & 1 deletion src/index.less
Expand Up @@ -30,7 +30,7 @@
border-radius: 3px;
margin-bottom: 16px;
background-color: var(--color-code-preview-bg) !important;
color: transparent !important;
jaywcjlove marked this conversation as resolved.
Show resolved Hide resolved
// color: transparent !important;
max-height: 420px;
min-height: 12px;
z-index: 10;
Expand Down
25 changes: 19 additions & 6 deletions src/useCodePreview.ts
@@ -1,10 +1,19 @@
import React, { useEffect, useRef } from 'react';
// @ts-ignore
import ReactDOMClient from 'react-dom/client';
import ReactDOM from 'react-dom';
import { useState } from 'react';
import { babelTransform } from './transform';
import { CodePreviewProps } from './';
import ReactDOM from 'react-dom';

export const getReactDOMClient = () => {
let _ReactDOM;
try {
// 使用 require 解决 react v17 ts 报错问题
_ReactDOM = require('react-dom/client');
} catch (err) {
// console.warn(`如果使用的是react-dom小于v18的版本,可以忽略此警告:${err}`)
}
return _ReactDOM;
};

export function useCodePreview(props: CodePreviewProps) {
const [demoDom, setDemoDom] = useState<HTMLDivElement>();
Expand All @@ -16,6 +25,10 @@ export function useCodePreview(props: CodePreviewProps) {
const [copied, setCopied] = useState(false);
const [code, setCode] = useState(props.code || '');

const ReactDOMClient = React.useMemo(() => {
return window.ReactDOM ? window.ReactDOM : getReactDOMClient();
}, []);

/** 通过缓存的方式 解决 react v18 中 的报错 ***/
// @ts-ignore
const cachesRef = React.useRef(new Map<string, ReactDOMClient.Root>([]));
Expand Down Expand Up @@ -51,9 +64,9 @@ export function useCodePreview(props: CodePreviewProps) {
ReactDOMClient: _ReactDOMClient,
...otherDeps
} = props.dependencies || {};
const V18ReactDOM = _ReactDOMClient || ReactDOMClient || _ReactDOM || ReactDOM;
let V18ReactDOM = _ReactDOMClient || ReactDOMClient || _ReactDOM || ReactDOM;
// 判断是否是 react v18版本
const isV18 = Reflect.has(V18ReactDOM || {}, 'createRoot');
const isV18 = Reflect.has(V18ReactDOM, 'createRoot');
const NewReactDOM = isV18 ? ReactDOMRender(V18ReactDOM) : V18ReactDOM;
Copy link
Member

Choose a reason for hiding this comment

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

@SunLxy 处理方法仍然有问题,我们的代码放到 codepen 和 codesandbox 中是可以预览的

image


try {
Expand All @@ -75,7 +88,7 @@ export function useCodePreview(props: CodePreviewProps) {
// react < v18 中写法替换
str = str.replace('ReactDOM.render', `ReactDOM.createRoot("${playerId.current}").render`);
// react v18 中写法替换
str = str.replace(`ReactDOMClient.createRoot(_mount_)`, `ReactDOM.createRoot("${playerId.current}")`);
str = str.replace(`ReactDOM.createRoot(_mount_)`, `ReactDOM.createRoot("${playerId.current}")`);
str = str.replace('_mount_', ``);
} else {
str = str.replace('_mount_', `document.getElementById('${playerId.current}')`);
Expand Down
7 changes: 3 additions & 4 deletions website/Example.tsx
Expand Up @@ -5,9 +5,9 @@ import * as UIW from 'uiw';

const defaultCode = `
import { Button, Divider, Icon } from 'uiw';
import ReactDOMClient from 'react-dom/client';
import ReactDOM from 'react-dom/client';

ReactDOM.render(
ReactDOM.createRoot(_mount_).render(
<div>
<Button type="primary">主要按钮</Button>
<Button type="success">成功按钮</Button>
Expand All @@ -16,7 +16,6 @@ ReactDOM.render(
<Button type="light">亮按钮</Button>
<Button type="dark">暗按钮</Button>
</div>,
_mount_
);`;

const Example = () => {
Expand Down Expand Up @@ -81,7 +80,7 @@ const Example = () => {
html: '<div id="root"></div>',
js: code.replace('_mount_', 'document.getElementById("root")'),
css_external: 'https://unpkg.com/uiw@3.2.6/dist/uiw.min.css',
js_external: `https://unpkg.com/react@16.x/umd/react.development.js;https://unpkg.com/react-dom@16.x/umd/react-dom.development.js;https://unpkg.com/uiw@4.7.2/dist/uiw.min.js;https://unpkg.com/@uiw/codepen-require-polyfill@1.0.12/index.js`,
js_external: `https://unpkg.com/react@18.x/umd/react.development.js;https://unpkg.com/react-dom@18.x/umd/react-dom.development.js;https://unpkg.com/uiw@4.7.2/dist/uiw.min.js;https://unpkg.com/@uiw/codepen-require-polyfill@1.0.12/index.js`,
},
});
function handleChange(keyName: string, e: React.ChangeEvent<HTMLInputElement>) {
Expand Down