Skip to content

Commit

Permalink
fix: 修复 forwardRef 组件的错误无法捕获
Browse files Browse the repository at this point in the history
  • Loading branch information
rainke committed Oct 11, 2023
1 parent 4684d31 commit d2258e3
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 19 deletions.
51 changes: 34 additions & 17 deletions packages/renderer-core/src/renderer/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import divFactory from '../components/Div';
import { IRenderComponent, IRendererProps, IRendererState } from '../types';
import { IPublicTypeNodeSchema, IPublicTypeRootSchema } from '@alilc/lowcode-types';
import logger from '../utils/logger';
import { cloneEnumerableProperty, isForwardRefType, wrapReactClass } from '@alilc/lowcode-utils';

export default function rendererFactory(): IRenderComponent {
const { PureComponent, Component, createElement, findDOMNode } = adapter.getRuntime();
const { PureComponent, Component, createElement, findDOMNode, forwardRef } = adapter.getRuntime();
const RENDERER_COMPS: any = adapter.getRenderers();
const BaseRenderer = baseRendererFactory();
const AppContext = contextFactory();
Expand Down Expand Up @@ -105,18 +106,7 @@ export default function rendererFactory(): IRenderComponent {
return SetComponent;
}

patchDidCatch(SetComponent: any) {
if (!this.isValidComponent(SetComponent)) {
return;
}
if (SetComponent.patchedCatch) {
return;
}
if (!SetComponent.prototype) {
return;
}
SetComponent.patchedCatch = true;

patchDidCatchForClassComponent(SetComponent: any) {
// Rax 的 getDerivedStateFromError 有 BUG,这里先用 componentDidCatch 来替代
// @see https://github.com/alibaba/rax/issues/2211
const originalDidCatch = SetComponent.prototype.componentDidCatch;
Expand All @@ -135,12 +125,12 @@ export default function rendererFactory(): IRenderComponent {
return engine.createElement(engine.getFaultComponent(), {
...this.props,
error: this.state.error,
componentName: this.props._componentName
componentName: this.props._componentName,
});
}
return originRender.call(this);
};
if(!(SetComponent.prototype instanceof PureComponent)) {
if (!(SetComponent.prototype instanceof PureComponent)) {
const originShouldComponentUpdate = SetComponent.prototype.shouldComponentUpdate;
SetComponent.prototype.shouldComponentUpdate = function (nextProps: IRendererProps, nextState: any) {
if (nextState && nextState.engineRenderError) {
Expand All @@ -151,10 +141,37 @@ export default function rendererFactory(): IRenderComponent {
}
}

patchDidCatch(SetComponent: any) {
if (isForwardRefType(SetComponent)) {
SetComponent.patchedCatch = true;
const Wrapper = wrapReactClass(SetComponent);
this.patchDidCatchForClassComponent(Wrapper);
return cloneEnumerableProperty(
forwardRef((props: any, ref: any) => {
return createElement(Wrapper, { ...props, forwardRef: ref });
}),
SetComponent,
);
}

if (!this.isValidComponent(SetComponent)) {
return;
}
if (SetComponent.patchedCatch) {
return;
}

if (!SetComponent.prototype) {
return;
}
SetComponent.patchedCatch = true;
this.patchDidCatchForClassComponent(SetComponent);
}

createElement(SetComponent: any, props: any, children?: any) {
// TODO: enable in runtime mode?
this.patchDidCatch(SetComponent);
return (this.props.customCreateElement || createElement)(SetComponent, props, children);
const PatchedComponent = this.patchDidCatch(SetComponent) || SetComponent;
return (this.props.customCreateElement || createElement)(PatchedComponent, props, children);
}

getNotFoundComponent() {
Expand Down
1 change: 0 additions & 1 deletion packages/renderer-core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ export interface IRenderComponent {
componentDidCatch(e: any): Promise<void> | void;
shouldComponentUpdate(nextProps: IRendererProps): boolean;
isValidComponent(SetComponent: any): any;
patchDidCatch(SetComponent: any): void;
createElement(SetComponent: any, props: any, children?: any): any;
getNotFoundComponent(): any;
getFaultComponent(): any;
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/is-react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function acceptsRef(obj: any): boolean {
return obj?.prototype?.isReactComponent || (obj.$$typeof && obj.$$typeof === REACT_FORWARD_REF_TYPE);
}

function isForwardRefType(obj: any): boolean {
export function isForwardRefType(obj: any): boolean {
return obj?.$$typeof && obj?.$$typeof === REACT_FORWARD_REF_TYPE;
}

Expand Down

0 comments on commit d2258e3

Please sign in to comment.