diff --git a/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPageDefault/hooks/useProgramMetadata.js b/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPageDefault/hooks/useProgramMetadata.js index d83f328f2b..542e07dfe6 100644 --- a/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPageDefault/hooks/useProgramMetadata.js +++ b/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPageDefault/hooks/useProgramMetadata.js @@ -4,6 +4,8 @@ import { useProgramFromIndexedDB } from '../../../../../utils/cachedDataHooks/us import { useDataElementsFromIndexedDB } from '../../../../../utils/cachedDataHooks/useDataElementsFromIndexedDB'; import { useOptionSetsFromIndexedDB } from '../../../../../utils/cachedDataHooks/useOptionSetsFromIndexedDB'; +const queryKey = 'useProgramMetadata'; + export const useProgramMetadata = (programId: string) => { const { program, isLoading, isError } = useProgramFromIndexedDB(programId, { enabled: !!programId }); @@ -17,10 +19,10 @@ export const useProgramMetadata = (programId: string) => { new Set) : undefined), [program]); const { - loading: loadingDataElements, + isLoading: loadingDataElements, dataElements, - error: dataElementsError, - } = useDataElementsFromIndexedDB(dataElementIds); + isError: dataElementsError, + } = useDataElementsFromIndexedDB([queryKey, programId], dataElementIds); const derivedDataElementValues = useMemo(() => (dataElements ? ({ @@ -37,10 +39,10 @@ export const useProgramMetadata = (programId: string) => { }) : undefined), [dataElements]); const { - loading: loadingOptionSets, + isLoading: loadingOptionSets, optionSets, - error: optionSetsError, - } = useOptionSetsFromIndexedDB(derivedDataElementValues && derivedDataElementValues.optionSetIds); + isError: optionSetsError, + } = useOptionSetsFromIndexedDB([queryKey, programId], derivedDataElementValues && derivedDataElementValues.optionSetIds); const optionSetDictionary = useMemo( () => (optionSets ? optionSets.reduce( diff --git a/src/core_modules/capture-core/utils/api/useQueryStyleEvaluation.js b/src/core_modules/capture-core/utils/api/useQueryStyleEvaluation.js deleted file mode 100644 index 2ada5c193b..0000000000 --- a/src/core_modules/capture-core/utils/api/useQueryStyleEvaluation.js +++ /dev/null @@ -1,33 +0,0 @@ -// @flow -import { useState, useEffect } from 'react'; - -// Caches result from previous evaluation -// Does not evaluate falsy input values - returns previously cached value instead -export const useQueryStyleEvaluation = (asyncFn: (input: any) => Promise, input: any) => { - const [loading, setLoading] = useState(false); - const [data, setData] = useState(); - const [error, setError] = useState(); - const [previousInput, setPreviousInput] = useState(); - - useEffect(() => { - if (input && input !== previousInput && !loading) { - setLoading(true); - setData(undefined); - setError(undefined); - setPreviousInput(input); - asyncFn(input).then((result) => { - setLoading(false); - setData(result); - }).catch((e) => { - setLoading(false); - setError(e); - }); - } - }, [loading, asyncFn, input, previousInput, setLoading, setData, setError, setPreviousInput]); - - return { - loading: loading || (!!input && input !== previousInput), - data, - error, - }; -}; diff --git a/src/core_modules/capture-core/utils/cachedDataHooks/useDataElementsFromIndexedDB.js b/src/core_modules/capture-core/utils/cachedDataHooks/useDataElementsFromIndexedDB.js index 666a438ec2..dbbf4f83c3 100644 --- a/src/core_modules/capture-core/utils/cachedDataHooks/useDataElementsFromIndexedDB.js +++ b/src/core_modules/capture-core/utils/cachedDataHooks/useDataElementsFromIndexedDB.js @@ -1,28 +1,32 @@ // @flow -import { useCallback } from 'react'; +import type { UseQueryOptions } from 'react-query'; import { userStores, getUserStorageController } from '../../storageControllers'; -import { useQueryStyleEvaluation } from '../api/useQueryStyleEvaluation'; +import { useIndexedDBQuery } from '../reactQueryHelpers'; import type { CachedDataElement } from '../../storageControllers/'; -export const useDataElementsFromIndexedDB = (dataElementIds: ?Set): { +export const useDataElementsFromIndexedDB = (queryKey: Array, dataElementIds: ?Set, queryOptions?: UseQueryOptions<>): { dataElements: ?Array, - loading: boolean, - error: any, + isLoading: boolean, + isError: boolean, } => { const storageController = getUserStorageController(); + const { enabled = !!dataElementIds } = queryOptions ?? {}; - const getDataElements = useCallback(requestedIds => - storageController.getAll( + const { data, isLoading, isError } = useIndexedDBQuery( + ['dataElements', ...queryKey], + () => storageController.getAll( userStores.DATA_ELEMENTS, { - predicate: dataElement => requestedIds.has(dataElement.id), + // $FlowIgnore - the enabled prop guarantees that dataElementIds will be defined + predicate: dataElement => dataElementIds.has(dataElement.id), }, - ), [storageController]); - - const { loading, data, error } = useQueryStyleEvaluation(getDataElements, dataElementIds); + ), { + enabled, + }, + ); return { dataElements: data, - loading, - error, + isLoading, + isError, }; }; diff --git a/src/core_modules/capture-core/utils/cachedDataHooks/useOptionSetsFromIndexedDB.js b/src/core_modules/capture-core/utils/cachedDataHooks/useOptionSetsFromIndexedDB.js index d7f51efd34..f0480779ee 100644 --- a/src/core_modules/capture-core/utils/cachedDataHooks/useOptionSetsFromIndexedDB.js +++ b/src/core_modules/capture-core/utils/cachedDataHooks/useOptionSetsFromIndexedDB.js @@ -1,28 +1,32 @@ // @flow -import { useCallback } from 'react'; +import type { UseQueryOptions } from 'react-query'; import { userStores, getUserStorageController } from '../../storageControllers'; -import { useQueryStyleEvaluation } from '../api/useQueryStyleEvaluation'; +import { useIndexedDBQuery } from '../reactQueryHelpers'; import type { CachedOptionSet } from '../../storageControllers/'; -export const useOptionSetsFromIndexedDB = (optionSetIds: ?Set): { +export const useOptionSetsFromIndexedDB = (queryKey: Array, optionSetIds: ?Set, queryOptions?: UseQueryOptions<>): { optionSets: ?Array, - loading: boolean, - error: any, + isLoading: boolean, + isError: boolean, } => { const storageController = getUserStorageController(); + const { enabled = !!optionSetIds } = queryOptions ?? {}; - const getOptionSets = useCallback(requestedIds => - storageController.getAll( + const { data, isLoading, isError } = useIndexedDBQuery( + ['optionSets', ...queryKey], + () => storageController.getAll( userStores.OPTION_SETS, { - predicate: optionSet => requestedIds.has(optionSet.id), + // $FlowIgnore - the enabled prop guarantees that optionSetIds will be defined + predicate: optionSet => optionSetIds.has(optionSet.id), }, - ), [storageController]); - - const { loading, data, error } = useQueryStyleEvaluation(getOptionSets, optionSetIds); + ), { + enabled, + }, + ); return { optionSets: data, - loading, - error, + isLoading, + isError, }; }; diff --git a/src/core_modules/capture-core/utils/reactQueryHelpers/query/useMetadataQuery.js b/src/core_modules/capture-core/utils/reactQueryHelpers/query/useMetadataQuery.js index ee31061b8c..2452405547 100644 --- a/src/core_modules/capture-core/utils/reactQueryHelpers/query/useMetadataQuery.js +++ b/src/core_modules/capture-core/utils/reactQueryHelpers/query/useMetadataQuery.js @@ -5,7 +5,7 @@ import { useDataEngine, type ResourceQuery } from '@dhis2/app-runtime'; import type { QueryFunction, UseQueryOptions } from 'react-query'; import { IndexedDBError } from '../../../../capture-core-utils/storage/IndexedDBError/IndexedDBError'; import type { Result } from './useMetadataQuery.types'; -import { ReactQueryAppNamespace } from '../reactQueryHelpers.const'; +import { ReactQueryAppNamespace, IndexedDBNamespace } from '../reactQueryHelpers.const'; const throwErrorForIndexedDB = (error) => { if (error instanceof IndexedDBError) { @@ -43,7 +43,7 @@ export const useIndexedDBQuery = ( queryFn: QueryFunction, queryOptions?: UseQueryOptions, ): Result => - useAsyncMetadata(queryKey, queryFn, { + useAsyncMetadata([IndexedDBNamespace, ...queryKey], queryFn, { cacheTime: 0, ...queryOptions, onError: (error) => { diff --git a/src/core_modules/capture-core/utils/reactQueryHelpers/reactQueryHelpers.const.js b/src/core_modules/capture-core/utils/reactQueryHelpers/reactQueryHelpers.const.js index 2659b304ba..5256c91b69 100644 --- a/src/core_modules/capture-core/utils/reactQueryHelpers/reactQueryHelpers.const.js +++ b/src/core_modules/capture-core/utils/reactQueryHelpers/reactQueryHelpers.const.js @@ -1,4 +1,4 @@ - // @flow export const ReactQueryAppNamespace = 'capture'; +export const IndexedDBNamespace = 'indexedDB';