diff --git a/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx b/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx index d64a8bb2ae27db0ebf2914cc096c307c8fb03429..9dbdff422c8106d41fac06e96b55e92efc77ab40 100644 --- a/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx +++ b/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx @@ -2,7 +2,7 @@ import { Edge, GraphQueryResult, Node, useML } from '@graphpolaris/shared/lib/da import { dataColors, visualizationColors } from 'config'; import { Viewport } from 'pixi-viewport'; import { Application, ColorSource, Container, FederatedPointerEvent, Graphics, IPointData, Point, Text } from 'pixi.js'; -import { useEffect, useRef, useState, useMemo, useImperativeHandle, forwardRef } from 'react'; +import { useEffect, useRef, useState, useMemo, useImperativeHandle, forwardRef, DependencyList } from 'react'; import { LinkType, NodeType } from '../types'; import { NLPopup } from './MatrixPopup'; @@ -46,6 +46,24 @@ type Props = { const columnsContainer = new Container(); +function useAsyncMemo<T>(factory: () => Promise<T> | undefined | null, deps: DependencyList, initial?: T) { + const [val, setVal] = useState<T | undefined>(initial) + useEffect(() => { + let cancel = false + const promise = factory() + if (promise === undefined || promise === null) return + promise.then((val) => { + if (!cancel) { + setVal(val) + } + }) + return () => { + cancel = true + } + }, deps) + return val +} + ////////////////// // MAIN COMPONENT ////////////////// @@ -64,8 +82,7 @@ export const MatrixPixi = forwardRef((props: Props, refExternal) => { useEffect(() => { if (props.graph && internalRef.current && imperative.current) { - if (isSetup.current === false) setup(); - else update(); + if (isSetup.current !== false) update(); } }, [props.graph, globalConfig.theme]); @@ -84,19 +101,30 @@ export const MatrixPixi = forwardRef((props: Props, refExternal) => { const ml = useML(); - const app = useMemo( - () => - new Application({ + const app = useAsyncMemo( + async () => { + if (canvas.current == null) return null; + const app = new Application(); + await app.init({ backgroundAlpha: 0, antialias: true, autoDensity: true, eventMode: 'auto', resolution: window.devicePixelRatio || 2, view: canvas.current as HTMLCanvasElement, - }), - [canvas.current], + }); + return app; + }, + [canvas] ); + useEffect(() => { + if (app == null) return; + + setup(); + }, + [app]); + useEffect(() => { if (typeof refExternal === 'function') { refExternal(internalRef.current); @@ -170,7 +198,7 @@ export const MatrixPixi = forwardRef((props: Props, refExternal) => { useEffect(() => { return () => { - app.destroy(); + app?.destroy(); } }, []); diff --git a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx index cf2d9f12696971ecd0e005fafd1ec95fc81b0f1e..f2e7a9e1c552bc92fbb6a37c53126c6211cfc1e0 100644 --- a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx +++ b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx @@ -65,7 +65,6 @@ export const NLPixi = forwardRef((props: Props, refExternal) => { const ref = useRef<HTMLDivElement>(null); const canvas = useRef<HTMLCanvasElement>(null); const app = useAsyncMemo( - async () => { if (canvas.current == null) return null; const app = new Application(); @@ -803,7 +802,7 @@ export const NLPixi = forwardRef((props: Props, refExternal) => { return () => { nodeMap.current.clear(); linkLabelMap.current.clear(); - app.destroy(); + app?.destroy(); const layout = layoutAlgorithm.current as GraphologyForceAtlas2Webworker; if (layout?.cleanup != null) layout.cleanup();