feat(core): make playground effect idempotent to support React.StrictMode (#387)

* feat(core): playground container create & dispose effect should be idempotent

* fix(core): outside cannot get playground ref
This commit is contained in:
Louis Young 2025-06-18 20:50:16 +08:00 committed by GitHub
parent cb36e753ab
commit 9190fbc6ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 12 deletions

View File

@ -1,4 +1,4 @@
import React, { useMemo, useImperativeHandle, forwardRef } from 'react';
import React, { useMemo, useImperativeHandle, forwardRef, useRef, useEffect } from 'react';
import { type interfaces } from 'inversify';
@ -59,18 +59,19 @@ export const PlaygroundReactProvider = forwardRef<
zoomEnable: true,
...others,
},
fromContainer,
fromContainer
);
if (playgroundContext) {
flowContainer.rebind(PlaygroundContext).toConstantValue(playgroundContext);
}
if (containerModules) {
containerModules.forEach(module => flowContainer.load(module));
containerModules.forEach((module) => flowContainer.load(module));
}
}
return flowContainer;
// @action 这里 props 数据如果更改不会触发刷新,不允许修改
}, []);
const playground = useMemo(() => {
const playground = container.get(Playground);
let ctx: PluginContext;
@ -87,6 +88,26 @@ export const PlaygroundReactProvider = forwardRef<
return playground;
}, []);
const effectSignalRef = useRef<number>(0);
useEffect(() => {
effectSignalRef.current += 1;
return () => {
// 开发环境下延迟处理 dispose防止 React>=18 useEffect 初始化卸载(在生产构建时,这个条件分支会被完全移除)
if (process.env.NODE_ENV === 'development') {
const FRAME = 16;
setTimeout(() => {
effectSignalRef.current -= 1;
if (effectSignalRef.current === 0) {
playground.dispose();
}
}, FRAME);
return;
}
playground.dispose();
};
}, []);
useImperativeHandle(ref, () => container.get<PluginContext>(PluginContext), []);
return (

View File

@ -22,15 +22,10 @@ export const PlaygroundReactRenderer: React.FC<PlaygroundReactRendererProps> = (
*
*/
useEffect(() => {
if (ref.current) {
playground.setParent(ref.current);
playground.ready();
if (playgroundConfig.autoFocus) {
playground.node.focus();
}
return () => {
playground.dispose();
};
playground.setParent(ref.current);
playground.ready();
if (playgroundConfig.autoFocus) {
playground.node.focus();
}
}, []);
const PlaygroundComp = playground.toReactComponent();