-
Notifications
You must be signed in to change notification settings - Fork 33
feat: DH-16737 Add ObjectManager, useWidget hook
#2030
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
ca6c2a8
33b87f5
cbcaf12
dbaa66b
4460f9b
6224d5e
322454d
6679a2a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,8 @@ | ||
| import { dh } from '@deephaven/jsapi-types'; | ||
| import Log from '@deephaven/log'; | ||
| import { assertNotNull } from '@deephaven/utils'; | ||
| import { useEffect, useState } from 'react'; | ||
| import { useEffect, useMemo, useState } from 'react'; | ||
| import useApi from './useApi'; | ||
| import { useObjectFetch } from './useObjectFetch'; | ||
|
|
||
| const log = Log.module('useWidget'); | ||
|
|
@@ -14,12 +15,12 @@ type WidgetWrapper<T extends dh.Widget = dh.Widget> = { | |
| widget: T | null; | ||
|
|
||
| /** Error status if there was an issue fetching the widget */ | ||
| error: unknown | null; | ||
| error: NonNullable<unknown> | null; | ||
| }; | ||
|
|
||
| /** | ||
| * Retrieve a widget for the given variable descriptor. Note that if the widget is successfully fetched, ownership of the widget is passed to the consumer and will need to close the object as well. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there frequently cases where we wouldn't want to just close this when
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, with a widget you can get updates that include new exported objects (like we do with deephaven.ui), those need to be cleaned up as well; or you may want to re-export exported objects rather than fetch them, I don't think we want to automatically close things here as it's not clear if the objects were actually fetched by the consumer or not. |
||
| * @param descriptor Descriptor to get the widget for | ||
| * @param descriptor Descriptor to get the widget for. Should be stable to avoid infinite re-fetching. | ||
| * @returns A WidgetWrapper object that contains the widget or an error status if there was an issue fetching the widget. Will contain nulls if still loading. | ||
| */ | ||
| export function useWidget<T extends dh.Widget = dh.Widget>( | ||
|
|
@@ -29,27 +30,50 @@ export function useWidget<T extends dh.Widget = dh.Widget>( | |
| widget: null, | ||
| error: null, | ||
| })); | ||
|
|
||
| const api = useApi(); | ||
| const unsupportedTypes = useMemo( | ||
| () => [ | ||
| api.VariableType.TABLE, | ||
| api.VariableType.TREETABLE, | ||
| api.VariableType.HIERARCHICALTABLE, | ||
| api.VariableType.TABLEMAP, | ||
| api.VariableType.PARTITIONEDTABLE, | ||
| api.VariableType.FIGURE, | ||
| api.VariableType.PANDAS, | ||
| api.VariableType.TREEMAP, | ||
| ], | ||
|
mofojed marked this conversation as resolved.
Outdated
|
||
| [api] | ||
| ); | ||
| const objectFetch = useObjectFetch<T>(descriptor); | ||
|
|
||
| useEffect( | ||
| function loadWidget() { | ||
| log.debug('loadWidget', descriptor); | ||
|
|
||
| const { fetch, error } = objectFetch; | ||
| if (unsupportedTypes.includes(descriptor.type)) { | ||
| // We only support fetching widgets with this hook | ||
| setWrapper({ | ||
| widget: null, | ||
| error: new Error(`Unsupported descriptor type: ${descriptor.type}`), | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| const { status } = objectFetch; | ||
|
|
||
| if (error != null) { | ||
| if (status === 'error') { | ||
| // We can't fetch if there's an error getting the fetcher, just return an error | ||
| setWrapper({ widget: null, error }); | ||
| setWrapper({ widget: null, error: objectFetch.error }); | ||
| return; | ||
| } | ||
|
|
||
| if (fetch == null) { | ||
| if (status === 'loading') { | ||
| // Still loading | ||
| setWrapper({ widget: null, error: null }); | ||
| return; | ||
| } | ||
|
|
||
| const { fetch } = objectFetch; | ||
| // We should be able to load the widget. Load it asynchronously, and set the widget when it's done. | ||
| // If we get cancelled before the fetch is done, we should close the widget and its exported objects. | ||
| // If not though, the consumer of the widget is expected to take ownership and close the widget appropriately. | ||
|
|
@@ -76,15 +100,15 @@ export function useWidget<T extends dh.Widget = dh.Widget>( | |
| return; | ||
| } | ||
| log.error('loadWidgetInternal error', descriptor, e); | ||
| setWrapper({ widget: null, error: e }); | ||
| setWrapper({ widget: null, error: e ?? new Error('Null error') }); | ||
| } | ||
| } | ||
| loadWidgetInternal(); | ||
| return () => { | ||
| isCancelled = true; | ||
| }; | ||
| }, | ||
| [descriptor, objectFetch] | ||
| [descriptor, objectFetch, unsupportedTypes] | ||
| ); | ||
|
|
||
| return wrapper; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.