Improves lazy loading.

This commit is contained in:
Henning Dieterichs
2020-10-08 10:50:19 +02:00
parent 5512c0b244
commit cf382c71c9
33 changed files with 498 additions and 280 deletions

View File

@@ -1,7 +1,12 @@
import * as React from "react";
import * as ReactDom from "react-dom";
import { Visualization, Theme } from "./index";
import { Visualizer, VisualizationId, asVisualizationId } from "./Visualizer";
import {
Visualizer,
VisualizationId,
asVisualizationId,
VisualizationRenderOptions,
} from "./Visualizer";
interface Options {
id?: string;
@@ -27,30 +32,91 @@ export abstract class BaseReactVisualization implements Visualization<unknown> {
public render(
target: HTMLDivElement,
theme: Theme,
previous: unknown | undefined
): unknown {
const node = this.getReactNode(theme);
options: VisualizationRenderOptions<unknown>
): { renderState: unknown } {
const node = this.getReactNode({
theme: options.theme,
readyCallback: options.readyCallback,
});
// We could use this to get access to theme vars:
// getComputedStyle(target).getPropertyValue("--background-color")
//getComputedStyle(target).getPropertyValue("--background-color")
ReactDom.render(<>{node}</>, target);
return undefined;
return { renderState: undefined };
}
protected abstract getReactNode(theme: Theme): React.ReactChild;
public abstract preload(): Promise<void>;
protected abstract getReactNode(
options: ReactVisualizationRenderOptions
): React.ReactChild;
}
export class ReactVisualization extends BaseReactVisualization {
export interface ReactVisualizationRenderOptions {
theme: Theme;
readyCallback: () => void;
}
class ReactVisualization extends BaseReactVisualization {
private readonly _preload?: () => Promise<void>;
constructor(
sourceVisualizer: Visualizer,
options: Options,
private readonly renderReactNode: (theme: Theme) => React.ReactChild
options: Options & { preload?: () => Promise<void> },
private readonly renderReactNode: (
options: ReactVisualizationRenderOptions
) => React.ReactChild
) {
super(sourceVisualizer, options);
this._preload = options.preload;
}
protected getReactNode(theme: Theme): React.ReactChild {
return this.renderReactNode(theme);
protected getReactNode(
options: ReactVisualizationRenderOptions
): React.ReactChild {
return this.renderReactNode(options);
}
public async preload(): Promise<void> {
if (this._preload) {
return await this._preload();
}
}
}
export function createReactVisualization(
sourceVisualizer: Visualizer,
options: Options & { preload?: () => Promise<void> },
renderReactNode: (options: { theme: Theme }) => React.ReactChild
) {
return new ReactVisualization(sourceVisualizer, options, options => (
<ComponentWithOnMount
onDidMount={options.readyCallback}
child={renderReactNode(options)}
/>
));
}
class ComponentWithOnMount extends React.Component<{
child: React.ReactChild;
onDidMount: () => void;
}> {
componentDidMount() {
this.props.onDidMount();
}
render() {
return this.props.child;
}
}
export function createLazyReactVisualization(
sourceVisualizer: Visualizer,
options: Options & { preload?: () => Promise<void> },
renderReactNode: (
options: ReactVisualizationRenderOptions
) => React.ReactChild
) {
return new ReactVisualization(sourceVisualizer, options, options =>
renderReactNode(options)
);
}