diff --git a/packages/rax-simulator-renderer/src/renderer.ts b/packages/rax-simulator-renderer/src/renderer.ts index e27a5e22e..c21051fa2 100644 --- a/packages/rax-simulator-renderer/src/renderer.ts +++ b/packages/rax-simulator-renderer/src/renderer.ts @@ -410,7 +410,9 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { }; } instance = Instance.get(dom); - while (instance && instance[INTERNAL]) { + + let loopNum = 0; // 防止由于某种意外而导致死循环 + while (instance && instance[INTERNAL] && loopNum < 1000) { if (isValidDesignModeRaxComponentInstance(instance)) { // if (instance && SYMBOL_VNID in instance) { // const docId = (instance.props as any).schema.docId; @@ -422,7 +424,8 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { }; } - instance = instance[INTERNAL].__parentInstance; + instance = getRaxVDomParentInstance(instance); + loopNum += 1; } return null; @@ -636,4 +639,21 @@ function getLowCodeComponentProps(props: any) { return newProps; } +/** + * 获取 Rax 里面 VDOM 的上一级的实例 + * 注意:Rax 的 development 的包是带有 __parentInstance, + * 但是 production 的包 __parentInstance 会被压缩掉, + * 所以这里遍历下其中的所有值,尝试找到有 _internal 的那个(别的值不会带有这个属性的) + */ +function getRaxVDomParentInstance(instance: { _internal: any }) { + const internalInstance = instance._internal; + return internalInstance.__parentInstance || + Object.values(internalInstance).find(v => ( + v !== null && + v !== instance && + typeof v === 'object' && + typeof (v as {_internal: unknown})._internal === 'object' + )); +} + export default new SimulatorRendererContainer(); diff --git a/packages/renderer-core/src/renderer/renderer.tsx b/packages/renderer-core/src/renderer/renderer.tsx index e444e7610..3ca21e46a 100644 --- a/packages/renderer-core/src/renderer/renderer.tsx +++ b/packages/renderer-core/src/renderer/renderer.tsx @@ -111,9 +111,17 @@ export default function rendererFactory() { return; } SetComponent.patchedCatch = true; - SetComponent.getDerivedStateFromError = (error: Error) => { - return { engineRenderError: true, error }; + + // Rax 的 getDerivedStateFromError 有 BUG,这里先用 componentDidCatch 来替代 + // @see https://github.com/alibaba/rax/issues/2211 + const originalDidCatch = SetComponent.prototype.componentDidCatch; + SetComponent.prototype.componentDidCatch = function didCatch(this: any, error: Error, errorInfo: any) { + this.setState({ engineRenderError: true, error }); + if (originalDidCatch && typeof originalDidCatch === 'function') { + originalDidCatch.call(this, error, errorInfo); + } }; + const engine = this; const originRender = SetComponent.prototype.render; SetComponent.prototype.render = function () {