Prefetching views and favorites (#4421)
* wip * Push * Complete work on prefetch * Add comment * Fix * Fix * Fix * Fix * Remove dead code * Simplify * Fix tests * Fix tests * Fix according to review * Fix according to review --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
|
||||
import { PrefetchRunQueriesEffect } from '@/prefetch/components/PrefetchRunQueriesEffect';
|
||||
|
||||
export const PrefetchDataProvider = ({ children }: React.PropsWithChildren) => {
|
||||
return (
|
||||
<>
|
||||
<PrefetchRunQueriesEffect />
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,53 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery';
|
||||
import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
||||
import { usePrefetchRunQuery } from '@/prefetch/hooks/internal/usePrefetchRunQuery';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const PrefetchRunQueriesEffect = () => {
|
||||
const {
|
||||
objectMetadataItem: objectMetadataItemView,
|
||||
upsertRecordsInCache: upsertViewsInCache,
|
||||
} = usePrefetchRunQuery({
|
||||
prefetchKey: PrefetchKey.AllViews,
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const {
|
||||
objectMetadataItem: objectMetadataItemFavorite,
|
||||
upsertRecordsInCache: upsertFavoritesInCache,
|
||||
} = usePrefetchRunQuery({
|
||||
prefetchKey: PrefetchKey.AllFavorites,
|
||||
objectNameSingular: CoreObjectNameSingular.Favorite,
|
||||
});
|
||||
|
||||
const prefetchFindManyQuery =
|
||||
useGenerateFindManyRecordsForMultipleMetadataItemsQuery({
|
||||
objectMetadataItems: [objectMetadataItemView, objectMetadataItemFavorite],
|
||||
depth: 2,
|
||||
});
|
||||
|
||||
if (!isDefined(prefetchFindManyQuery)) {
|
||||
throw new Error('Could not prefetch recrds');
|
||||
}
|
||||
|
||||
const { data } = useQuery<MultiObjectRecordQueryResult>(
|
||||
prefetchFindManyQuery,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(data?.views)) {
|
||||
upsertViewsInCache(data.views);
|
||||
}
|
||||
|
||||
if (isDefined(data?.favorites)) {
|
||||
upsertFavoritesInCache(data.favorites);
|
||||
}
|
||||
}, [data, upsertViewsInCache, upsertFavoritesInCache]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -0,0 +1,9 @@
|
||||
import { QueryKey } from '@/object-record/query-keys/types/QueryKey';
|
||||
import { ALL_FAVORITES_QUERY_KEY } from '@/prefetch/query-keys/AllFavoritesQueryKey';
|
||||
import { ALL_VIEWS_QUERY_KEY } from '@/prefetch/query-keys/AllViewsQueryKey';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export const PREFETCH_CONFIG: Record<PrefetchKey, QueryKey> = {
|
||||
ALL_VIEWS: ALL_VIEWS_QUERY_KEY,
|
||||
ALL_FAVORITES: ALL_FAVORITES_QUERY_KEY,
|
||||
};
|
||||
@ -0,0 +1,55 @@
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpsertFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useUpsertFindManyRecordsQueryInCache';
|
||||
import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
import { ALL_VIEWS_QUERY_KEY } from '@/prefetch/query-keys/AllViewsQueryKey';
|
||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export type UsePrefetchRunQuery = {
|
||||
prefetchKey: PrefetchKey;
|
||||
objectNameSingular: CoreObjectNameSingular;
|
||||
};
|
||||
|
||||
export const usePrefetchRunQuery = <T extends ObjectRecord>({
|
||||
prefetchKey,
|
||||
objectNameSingular,
|
||||
}: UsePrefetchRunQuery) => {
|
||||
const setPrefetchDataIsLoadedLoaded = useSetRecoilState(
|
||||
prefetchIsLoadedFamilyState(prefetchKey),
|
||||
);
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: objectNameSingular,
|
||||
});
|
||||
|
||||
const { upsertFindManyRecordsQueryInCache } =
|
||||
useUpsertFindManyRecordsQueryInCache({
|
||||
objectMetadataItem: objectMetadataItem,
|
||||
});
|
||||
|
||||
const mapConnectionToRecords = useMapConnectionToRecords();
|
||||
|
||||
const upsertRecordsInCache = (records: ObjectRecordConnection<T>) => {
|
||||
upsertFindManyRecordsQueryInCache({
|
||||
queryVariables: ALL_VIEWS_QUERY_KEY.variables,
|
||||
depth: ALL_VIEWS_QUERY_KEY.depth,
|
||||
objectRecordsToOverwrite:
|
||||
mapConnectionToRecords({
|
||||
objectRecordConnection: records,
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
depth: 2,
|
||||
}) ?? [],
|
||||
});
|
||||
setPrefetchDataIsLoadedLoaded(true);
|
||||
};
|
||||
|
||||
return {
|
||||
objectMetadataItem,
|
||||
setPrefetchDataIsLoadedLoaded,
|
||||
upsertRecordsInCache,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,27 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
|
||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export const usePrefetchedData = <T extends ObjectRecord>(
|
||||
prefetchKey: PrefetchKey,
|
||||
) => {
|
||||
const isDataPrefetched = useRecoilValue(
|
||||
prefetchIsLoadedFamilyState(prefetchKey),
|
||||
);
|
||||
const prefetchQueryKey = PREFETCH_CONFIG[prefetchKey];
|
||||
|
||||
const { records } = useFindManyRecords<T>({
|
||||
skip: !isDataPrefetched,
|
||||
...prefetchQueryKey,
|
||||
useRecordsWithoutConnection: true,
|
||||
});
|
||||
|
||||
return {
|
||||
isDataPrefetched,
|
||||
records,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { QueryKey } from '@/object-record/query-keys/types/QueryKey';
|
||||
|
||||
export const ALL_FAVORITES_QUERY_KEY: QueryKey = {
|
||||
objectNameSingular: CoreObjectNameSingular.Favorite,
|
||||
variables: {},
|
||||
depth: 1,
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { QueryKey } from '@/object-record/query-keys/types/QueryKey';
|
||||
|
||||
export const ALL_VIEWS_QUERY_KEY: QueryKey = {
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
variables: {},
|
||||
depth: 1,
|
||||
};
|
||||
@ -0,0 +1,10 @@
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState';
|
||||
|
||||
export const prefetchIsLoadedFamilyState = createFamilyState<
|
||||
boolean,
|
||||
PrefetchKey
|
||||
>({
|
||||
key: 'prefetchIsLoadedFamilyState',
|
||||
defaultValue: false,
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
export enum PrefetchKey {
|
||||
AllViews = 'ALL_VIEWS',
|
||||
AllFavorites = 'ALL_FAVORITES',
|
||||
}
|
||||
Reference in New Issue
Block a user