diff --git a/packages/istanbul-widget/CHANGELOG.md b/packages/istanbul-widget/CHANGELOG.md index 17cf053..c81cce3 100644 --- a/packages/istanbul-widget/CHANGELOG.md +++ b/packages/istanbul-widget/CHANGELOG.md @@ -1,5 +1,11 @@ # istanbul-widget +## 1.5.4 + +### Patch Changes + +- fix: react-dom asyn render leading to issue in safari + ## 1.5.3 ### Patch Changes diff --git a/packages/istanbul-widget/package.json b/packages/istanbul-widget/package.json index bc9c47c..da306e0 100644 --- a/packages/istanbul-widget/package.json +++ b/packages/istanbul-widget/package.json @@ -1,6 +1,6 @@ { "name": "istanbul-widget", - "version": "1.5.3", + "version": "1.5.4", "type": "module", "homepage": "https://github.com/hemengke1997/istanbul-toolkit/tree/master/packages/istanbul-widget", "files": [ diff --git a/packages/istanbul-widget/src/core/core.ts b/packages/istanbul-widget/src/core/core.ts index 50cec75..e84d6c4 100644 --- a/packages/istanbul-widget/src/core/core.ts +++ b/packages/istanbul-widget/src/core/core.ts @@ -68,7 +68,7 @@ export class IstanbulWidget { this._addBuiltInPlugins() // try to init - const _onload = () => { + const _onload = async () => { if (this.isInited) { return } @@ -96,7 +96,7 @@ export class IstanbulWidget { } } - private _initComponent() { + private async _initComponent() { if (!$.one(`#${ISTANBUL_WIDGET_ID}`)) { let target: HTMLElement = document.body if (typeof this.option.target === 'string') { diff --git a/packages/istanbul-widget/src/core/dom/react-render.ts b/packages/istanbul-widget/src/core/dom/react-render.ts new file mode 100644 index 0000000..6d1899a --- /dev/null +++ b/packages/istanbul-widget/src/core/dom/react-render.ts @@ -0,0 +1,23 @@ +import { type ReactElement } from 'react' +import { flushSync } from 'react-dom' +import ReactDOM, { type Root } from 'react-dom/client' + +const MARK = '__istanbul_widget_root__' + +type ContainerType = (Element | DocumentFragment) & { + [MARK]?: Root +} + +export function reactdomRender(node: ReactElement, container: ContainerType) { + flushSync(() => { + const root = container[MARK] || ReactDOM.createRoot(container) + root.render(node) + container[MARK] = root + }) +} + +export async function reactdomUnmount(container: ContainerType) { + await Promise.resolve() + container[MARK]?.unmount() + delete container[MARK] +} diff --git a/packages/istanbul-widget/src/core/plugin/IstanbulWidgetPlugin.ts b/packages/istanbul-widget/src/core/plugin/IstanbulWidgetPlugin.ts index f58c206..55d07d4 100644 --- a/packages/istanbul-widget/src/core/plugin/IstanbulWidgetPlugin.ts +++ b/packages/istanbul-widget/src/core/plugin/IstanbulWidgetPlugin.ts @@ -6,7 +6,7 @@ import { type IstanbulWidget } from '../core' type Events = { init: [] ready: [] - render: [callback: (res: { htmlElement: HTMLElement | undefined }) => void] + render: [callback: (res: { htmlElement: HTMLElement | undefined }) => void | Promise] } export class IstanbulWidgetPlugin { @@ -96,8 +96,8 @@ export class IstanbulWidgetPlugin { } public onRender() { - this.on('render', (callback) => { - callback({ htmlElement: this.htmlElement }) + this.on('render', async (callback) => { + await callback({ htmlElement: this.htmlElement }) }) } diff --git a/packages/istanbul-widget/src/core/plugin/IstanbulWidgetReactPlugin.ts b/packages/istanbul-widget/src/core/plugin/IstanbulWidgetReactPlugin.ts index 364f4d7..c3042e0 100644 --- a/packages/istanbul-widget/src/core/plugin/IstanbulWidgetReactPlugin.ts +++ b/packages/istanbul-widget/src/core/plugin/IstanbulWidgetReactPlugin.ts @@ -1,15 +1,14 @@ import React from 'react' -import ReactDOM from 'react-dom/client' import { $ } from '@/utils/query' import { IstanbulWidget } from '../core' +import { reactdomRender, reactdomUnmount } from '../dom/react-render' import { type PluginType } from '../options.interface' import { IstanbulWidgetPlugin } from './IstanbulWidgetPlugin' export type IstanbulWidgetReactPluginProps = {} & PluginType export class IstanbulWidgetReactPlugin extends IstanbulWidgetPlugin { - private _root!: ReactDOM.Root - + private _root!: HTMLDivElement constructor( /** * 插件id @@ -35,16 +34,18 @@ export class IstanbulWidgetReactPlugin extends IstanbulWidget onRender() { this.on('render', () => { const el = document.createElement('div') - const root = ReactDOM.createRoot(el) - root.render( + + this._root = el + + reactdomRender( React.createElement(this.Component, { ...((this.initialProps || {}) as T), id: this.id, name: this.name, domID: this.domID, }), + el, ) - this._root = root const target = $.queryEl(`#${this.domID}`) target.appendChild(el) @@ -57,7 +58,7 @@ export class IstanbulWidgetReactPlugin extends IstanbulWidget if (!this._root) { IstanbulWidget.logger.warn('[istanbul-widget]: init component first') } else { - this._root.unmount() + reactdomUnmount(this._root) } } } diff --git a/packages/istanbul-widget/src/core/render.tsx b/packages/istanbul-widget/src/core/render.tsx index 6a185e3..7fd6f1a 100644 --- a/packages/istanbul-widget/src/core/render.tsx +++ b/packages/istanbul-widget/src/core/render.tsx @@ -1,7 +1,7 @@ -import ReactDOM from 'react-dom/client' import { ISTANBUL_WIDGET_ID } from '@/utils/const' import Context, { type InitialWidgetProps } from './Context' import IstanbulWidget from './IstanbulWidget' +import { reactdomRender, reactdomUnmount } from './dom/react-render' import { type PluginType } from './options.interface' export type CompInstance = { @@ -19,19 +19,20 @@ export function render({ const container = document.createElement('div') container.id = ISTANBUL_WIDGET_ID target.appendChild(container) - const reactRoot = ReactDOM.createRoot(container) - reactRoot.render( + + reactdomRender( , + container, ) return { destroy() { - reactRoot.unmount() + reactdomUnmount(container) }, - update(newProps) { - reactRoot.render( + async update(newProps) { + reactdomRender( , + container, ) - return new Promise((resolve) => { - requestIdleCallback(() => { - resolve(true) - }) - }) + return true }, } } diff --git a/packages/vite-plugin-istanbul-widget/CHANGELOG.md b/packages/vite-plugin-istanbul-widget/CHANGELOG.md index 533e776..bb5a477 100644 --- a/packages/vite-plugin-istanbul-widget/CHANGELOG.md +++ b/packages/vite-plugin-istanbul-widget/CHANGELOG.md @@ -1,5 +1,12 @@ # vite-plugin-istanbul-widget +## 1.5.6 + +### Patch Changes + +- Updated dependencies + - istanbul-widget@1.5.4 + ## 1.5.5 ### Patch Changes diff --git a/packages/vite-plugin-istanbul-widget/package.json b/packages/vite-plugin-istanbul-widget/package.json index bbeaf81..77a4722 100644 --- a/packages/vite-plugin-istanbul-widget/package.json +++ b/packages/vite-plugin-istanbul-widget/package.json @@ -1,6 +1,6 @@ { "name": "vite-plugin-istanbul-widget", - "version": "1.5.5", + "version": "1.5.6", "type": "module", "homepage": "https://github.com/hemengke1997/istanbul-toolkit/tree/master/packages/vite-plugin-istanbul-widget", "main": "./dist/index.cjs",