Skip to content

Commit

Permalink
fix: 修复 react 17 中报错问题 (#216) (#217)
Browse files Browse the repository at this point in the history
  • Loading branch information
SunLxy committed Apr 23, 2022
1 parent 868d784 commit e98476c
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 15 deletions.
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;
// 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;

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

2 comments on commit e98476c

@vercel
Copy link

@vercel vercel bot commented on e98476c Apr 23, 2022

Choose a reason for hiding this comment

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

@jaywcjlove
Copy link
Member

Choose a reason for hiding this comment

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

Please sign in to comment.