优化 loadRenderer 逻辑,减少返回约束

This commit is contained in:
liaoxuezhi 2019-05-19 18:08:11 +08:00
parent 27c2bc721e
commit 3a0c332cde
4 changed files with 81 additions and 25 deletions

View File

@ -1,6 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`factory custom loadRenderer 1`] = ` exports[`factory custom not found 2! 1`] = `
<div>
<div>
Not Found
</div>
</div>
`;
exports[`factory custom not found 3! 1`] = `
<div>
<div>
Not Found
</div>
</div>
`;
exports[`factory custom not found! 1`] = `
<div> <div>
<div> <div>
Not Found Not Found

View File

@ -19,7 +19,7 @@ test('factory unregistered Renderer', async () => {
expect(container).toMatchSnapshot(); // not found expect(container).toMatchSnapshot(); // not found
}); });
test('factory custom loadRenderer', async () => { test('factory custom not found!', async () => {
const { const {
container, container,
} = render(amisRender({ } = render(amisRender({
@ -32,6 +32,32 @@ test('factory custom loadRenderer', async () => {
expect(container).toMatchSnapshot(); // not found expect(container).toMatchSnapshot(); // not found
}); });
test('factory custom not found 2!', async () => {
const {
container,
} = render(amisRender({
type: 'my-renderer',
a: 23
}, {}, makeEnv({
loadRenderer: () => () => (<div>Not Found</div>)
})));
await wait(100);
expect(container).toMatchSnapshot(); // not found
});
test('factory custom not found 3!', async () => {
const {
container,
} = render(amisRender({
type: 'my-renderer',
a: 23
}, {}, makeEnv({
loadRenderer: () => (<div>Not Found</div>)
})));
await wait(100);
expect(container).toMatchSnapshot(); // not found
});
test('factory load Renderer on need', async () => { test('factory load Renderer on need', async () => {
const { const {
container, container,
@ -55,16 +81,9 @@ test('factory load Renderer on need', async () => {
component: MyComponent, component: MyComponent,
test: /\bmy-renderer2$/ test: /\bmy-renderer2$/
}); });
return Promise.resolve(({
retry
}) => {
retry();
return null;
})
} }
}))); })));
await wait(200); await wait(100);
expect(container).toMatchSnapshot(); // not found expect(container).toMatchSnapshot(); // not found
}); });

View File

@ -29,6 +29,7 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
partialVisibility: true, partialVisibility: true,
}; };
mounted:boolean = false;
constructor(props: LazyComponentProps) { constructor(props: LazyComponentProps) {
super(props); super(props);
@ -40,6 +41,14 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
}; };
} }
componentWillMount() {
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
handleVisibleChange(visible: boolean) { handleVisibleChange(visible: boolean) {
this.setState({ this.setState({
visible: visible, visible: visible,
@ -52,12 +61,12 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
this.props this.props
.getComponent() .getComponent()
.then(component => .then(component =>
this.setState({ this.mounted && typeof component === 'function' && this.setState({
component: component, component: component,
}) })
) )
.catch(reason => .catch(reason =>
this.setState({ this.mounted && this.setState({
component: () => <div className="alert alert-danger">{String(reason)}</div>, component: () => <div className="alert alert-danger">{String(reason)}</div>,
}) })
); );

View File

@ -9,7 +9,7 @@ import {
getEnv getEnv
} from 'mobx-state-tree'; } from 'mobx-state-tree';
import { import {
Location Location, parsePath
} from 'history'; } from 'history';
import { import {
wrapFetcher wrapFetcher
@ -80,7 +80,7 @@ export interface RendererEnv {
affixOffsetTop: number; affixOffsetTop: number;
affixOffsetBottom: number; affixOffsetBottom: number;
richTextToken: string; richTextToken: string;
loadRenderer: (schema:Schema, path:string) => Promise<React.ReactType>; loadRenderer: (schema:Schema, path:string, reRender:Function) => Promise<React.ReactType> | React.ReactType | JSX.Element | void;
[propName:string]: any; [propName:string]: any;
}; };
@ -134,7 +134,7 @@ export interface RenderOptions {
rendererResolver?: (path:string, schema:Schema, props:any) => null | RendererConfig; rendererResolver?: (path:string, schema:Schema, props:any) => null | RendererConfig;
copy?: (contents:string) => void; copy?: (contents:string) => void;
getModalContainer?: () => HTMLElement; getModalContainer?: () => HTMLElement;
loadRenderer?: (schema:Schema, path: string) => Promise<React.ReactType>; loadRenderer?: (schema:Schema, path: string, reRender:Function) => Promise<React.ReactType> | React.ReactType | JSX.Element | void;
affixOffsetTop?: number; affixOffsetTop?: number;
affixOffsetBottom?: number; affixOffsetBottom?: number;
richTextToken?: string; richTextToken?: string;
@ -434,7 +434,17 @@ class SchemaRenderer extends React.Component<SchemaRendererProps, any> {
return ( return (
<LazyComponent <LazyComponent
{...rest} {...rest}
getComponent={() => rest.env.loadRenderer(schema, $path)} getComponent={async () => {
const result = await rest.env.loadRenderer(schema, $path, this.reRender);
if (result && typeof result === "function") {
return result;
} else if (result && React.isValidElement(result)) {
return () => result;
}
this.reRender();
return () => loadRenderer(schema, $path)
}}
$path={$path} $path={$path}
retry={this.reRender} retry={this.reRender}
/> />
@ -626,20 +636,22 @@ export function HocStoreFactory(renderer:{
} }
const defaultOptions:RenderOptions = { function loadRenderer(schema:Schema, path:string) {
session: 'global', return (
affixOffsetTop: 50,
affixOffsetBottom: 0,
richTextToken: '',
loadRenderer(schema, path) {
return Promise.resolve(() => (
<Alert level="danger"> <Alert level="danger">
<p>Error: </p> <p>Error: </p>
<p>Path: {path}</p> <p>Path: {path}</p>
<pre><code>{JSON.stringify(schema, null, 2)}</code></pre> <pre><code>{JSON.stringify(schema, null, 2)}</code></pre>
</Alert> </Alert>
)); );
}, }
const defaultOptions:RenderOptions = {
session: 'global',
affixOffsetTop: 50,
affixOffsetBottom: 0,
richTextToken: '',
loadRenderer,
fetcher() { fetcher() {
return Promise.reject('fetcher is required'); return Promise.reject('fetcher is required');
}, },