diff --git a/plugins/ui/src/js/src/ObjectView.tsx b/plugins/ui/src/js/src/ObjectView.tsx index 987068ef5..5a6f4eb95 100644 --- a/plugins/ui/src/js/src/ObjectView.tsx +++ b/plugins/ui/src/js/src/ObjectView.tsx @@ -13,7 +13,11 @@ function ObjectView(props: ObjectViewProps) { const { object } = props; log.info('Object is', object); - const fetch = useCallback(() => object.fetch() as Promise, [object]); + const fetch = useCallback(async () => { + // We reexport the object in case this object is used in multiplate places or closed/opened multiple times + const reexportedObject = await object.reexport(); + return reexportedObject.fetch() as Promise; + }, [object]); const plugins = usePlugins(); diff --git a/plugins/ui/src/js/src/UITable.tsx b/plugins/ui/src/js/src/UITable.tsx index 7106650b8..d1f971df5 100644 --- a/plugins/ui/src/js/src/UITable.tsx +++ b/plugins/ui/src/js/src/UITable.tsx @@ -19,12 +19,20 @@ function UITable({ element }: UITableProps) { // Just load the object on mount useEffect(() => { + let isCancelled = false; async function loadModel() { log.debug('Loading table from props', element.props); - const newTable = (await element.props.table.fetch()) as Table; + const reexportedTable = await element.props.table.reexport(); + const newTable = (await reexportedTable.fetch()) as Table; + if (isCancelled) { + newTable.close(); + } setTable(newTable); } loadModel(); + return () => { + isCancelled = true; + }; }, [dh, element]); const irisGridProps: Partial = useMemo(() => { diff --git a/plugins/ui/src/js/src/WidgetHandler.tsx b/plugins/ui/src/js/src/WidgetHandler.tsx index cb2283dd4..9f2df8dfb 100644 --- a/plugins/ui/src/js/src/WidgetHandler.tsx +++ b/plugins/ui/src/js/src/WidgetHandler.tsx @@ -160,6 +160,10 @@ function WidgetHandler({ onClose, widget: wrapper }: WidgetHandlerProps) { if (widget == null) { return; } + // Need to reset the exported object map and count + const widgetExportedObjectMap = new Map(); + exportedObjectMap.current = widgetExportedObjectMap; + exportedObjectCount.current = 0; function receiveData( data: string, newExportedObjects: WidgetExportedObject[] @@ -184,8 +188,14 @@ function WidgetHandler({ onClose, widget: wrapper }: WidgetHandlerProps) { receiveData(widget.getDataAsString(), widget.exportedObjects); return () => { - log.debug('Cleaning up listener'); + log.debug('Cleaning up widget', widget); cleanup(); + widget.close(); + + // Clean up any exported objects that haven't been closed yet + Array.from(widgetExportedObjectMap.values()).forEach(exportedObject => { + exportedObject.close(); + }); }; }, [dh, jsonClient, parseDocument, updateExportedObjects, widget]); @@ -194,9 +204,12 @@ function WidgetHandler({ onClose, widget: wrapper }: WidgetHandlerProps) { log.debug('loadWidget', wrapper.id, wrapper.definition); let isCancelled = false; async function loadWidgetInternal() { - const newWidget = await wrapper.fetch(false); + const newWidget = await wrapper.fetch(); if (isCancelled) { newWidget.close(); + newWidget.exportedObjects.forEach(exportedObject => { + exportedObject.close(); + }); return; } log.debug('newWidget', wrapper.id, wrapper.definition, newWidget); @@ -210,14 +223,6 @@ function WidgetHandler({ onClose, widget: wrapper }: WidgetHandlerProps) { [wrapper] ); - useEffect( - () => - function closeWidget() { - widget?.close(); - }, - [widget] - ); - const handleDocumentClose = useCallback(() => { log.debug('Widget document closed', wrapper.id); onClose?.(wrapper.id);