Skip to content

Commit

Permalink
#363: created useProjectDataProvider hook
Browse files Browse the repository at this point in the history
  • Loading branch information
tombogle committed Oct 6, 2023
1 parent e2c0ddb commit 2f783c6
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
10 changes: 6 additions & 4 deletions src/renderer/hooks/papi-hooks/use-data-provider.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { isString } from '@shared/utils/util';

/**
* Gets a data provider with specified provider name
* @param dataProviderSource string name of the data provider to get OR dataProvider (result of useDataProvider if you
* want this hook to just return the data provider again)
* @param dataProviderSource string name of the data provider to get OR dataProvider (result of
* useDataProvider, if you want this hook to just return the data provider again)
* @returns undefined if the data provider has not been retrieved,
* data provider if it has been retrieved and is not disposed,
* and undefined again if the data provider is disposed
Expand All @@ -24,7 +24,8 @@ function useDataProvider<T extends IDataProvider<any>>(
const didReceiveDataProvider = !isString(dataProviderSource);

// Get the data provider for this data provider name
// Note: do nothing if we received a data provider, but still run this hook. We must make sure to run the same number of hooks in all code paths)
// Note: do nothing if we already received a data provider, but still run this hook.
// (We must make sure to run the same number of hooks in all code paths.)
const [dataProvider] = usePromise(
useMemo(() => {
return didReceiveDataProvider
Expand All @@ -41,7 +42,8 @@ function useDataProvider<T extends IDataProvider<any>>(
);

// Disable this hook when the data provider is disposed
// Note: do nothing if we received a data provider, but still run this hook. We must make sure to run the same number of hooks in all code paths)
// Note: do nothing if we already received a data provider, but still run this hook.
// (We must make sure to run the same number of hooks in all code paths.)
const [isDisposed, setIsDisposed] = useState<boolean>(false);
useEvent(
!didReceiveDataProvider && dataProvider && !isDisposed ? dataProvider.onDidDispose : undefined,
Expand Down
61 changes: 61 additions & 0 deletions src/renderer/hooks/papi-hooks/use-project-data-provider.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import projectDataProviderService from '@shared/services/data-provider.service';
import IProjectDataProvider from '@shared/models/data-provider.interface';
import { useCallback, useMemo, useState } from 'react';
import useEvent from '@renderer/hooks/papi-hooks/use-event.hook';
import usePromise from '@renderer/hooks/papi-hooks/use-promise.hook';
import { isString } from '@shared/utils/util';

/**
* Gets a project data provider with specified provider name
* @param dataProviderSource string name of the data provider to get OR projectDataProvider (result
* of useProjectDataProvider, if you want this hook to just return the data provider again)
* @returns undefined if the project data provider has not been retrieved, the requested project
* data provider if it has been retrieved and is not disposed, and undefined again if the project
* data provider is disposed
*
* @type `T` - the type of project data provider to return. Use
* `IProjectDataProvider<TProjectDataProviderDataTypes>`, specifying your own types, or provide a
* custom project data provider type
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function useProjectDataProvider<T extends IProjectDataProvider<any>>(
dataProviderSource: string | T | undefined,
): T | undefined {
// Check to see if they passed in the results of a useDataProvider hook or undefined
const didReceiveDataProvider = !isString(dataProviderSource);

// Get the requested project data provider
// Note: do nothing if we have already received a project data provider, but still run this hook.
// (We must make sure to run the same number of hooks in all code paths.)
const [dataProvider] = usePromise(
useMemo(() => {
return didReceiveDataProvider
? // We already have a project data provider or undefined, so we don't need to run this promise
undefined
: async () =>
// We have the project data provider's type, so we need to get the provider
dataProviderSource
? // Type assert here - the user of this hook must make sure to provide the correct type
(projectDataProviderService.get(dataProviderSource) as Promise<T | undefined>)
: undefined;
}, [didReceiveDataProvider, dataProviderSource]),
undefined,
);

// Disable this hook when the project data provider is disposed
// Note: do nothing if we already received a project data provider, but still run this hook.
// (We must make sure to run the same number of hooks in all code paths.)
const [isDisposed, setIsDisposed] = useState<boolean>(false);
useEvent(
!didReceiveDataProvider && dataProvider && !isDisposed ? dataProvider.onDidDispose : undefined,
useCallback(() => setIsDisposed(true), []),
);

// If we received a data provider or undefined, return it
if (didReceiveDataProvider) return dataProviderSource;

// If we had to get a data provider, return it if it is not disposed
return dataProvider && !isDisposed ? dataProvider : undefined;
}

export default useProjectDataProvider;

0 comments on commit 2f783c6

Please sign in to comment.