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:
Charles Bochet
2024-03-15 18:35:40 +01:00
committed by GitHub
parent 38f28de4a6
commit afb9b3e375
21 changed files with 279 additions and 129 deletions

View File

@ -1,24 +1,18 @@
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { QueryMethodName } from '@/object-metadata/types/QueryMethodName';
import { useCachedRootQuery } from '@/object-record/cache/hooks/useCachedRootQuery';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
export const useDefaultHomePagePath = () => {
const { objectMetadataItem: companyObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.Company,
});
const { objectMetadataItem: viewObjectMetadataItem } = useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.View,
});
const { cachedRootQuery } = useCachedRootQuery({
objectMetadataItem: viewObjectMetadataItem,
queryMethodName: QueryMethodName.FindMany,
});
const companyViewId = cachedRootQuery?.views?.edges?.find(
(view: any) =>
view?.node?.objectMetadataId === companyObjectMetadataItem.id,
const { records } = usePrefetchedData(PrefetchKey.AllViews);
const companyViewId = records.find(
(view: any) => view?.objectMetadataId === companyObjectMetadataItem.id,
)?.node.id;
const defaultHomePagePath =
'/objects/companies' + (companyViewId ? `?view=${companyViewId}` : '');

View File

@ -13,6 +13,7 @@ import { ExceptionHandlerProvider } from '@/error-handler/components/ExceptionHa
import { PromiseRejectionEffect } from '@/error-handler/components/PromiseRejectionEffect';
import { ApolloMetadataClientProvider } from '@/object-metadata/components/ApolloMetadataClientProvider';
import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider';
import { PrefetchDataProvider } from '@/prefetch/components/PrefetchDataProvider';
import { IconsProvider } from '@/ui/display/icon/components/IconsProvider';
import { DialogManager } from '@/ui/feedback/dialog-manager/components/DialogManager';
import { DialogManagerScope } from '@/ui/feedback/dialog-manager/scopes/DialogManagerScope';
@ -47,18 +48,20 @@ root.render(
<UserProvider>
<ApolloMetadataClientProvider>
<ObjectMetadataItemsProvider>
<AppThemeProvider>
<SnackBarProvider>
<DialogManagerScope dialogManagerScopeId="dialog-manager">
<DialogManager>
<StrictMode>
<PromiseRejectionEffect />
<App />
</StrictMode>
</DialogManager>
</DialogManagerScope>
</SnackBarProvider>
</AppThemeProvider>
<PrefetchDataProvider>
<AppThemeProvider>
<SnackBarProvider>
<DialogManagerScope dialogManagerScopeId="dialog-manager">
<DialogManager>
<StrictMode>
<PromiseRejectionEffect />
<App />
</StrictMode>
</DialogManager>
</DialogManagerScope>
</SnackBarProvider>
</AppThemeProvider>
</PrefetchDataProvider>
<PageChangeEffect />
</ObjectMetadataItemsProvider>
</ApolloMetadataClientProvider>

View File

@ -6,38 +6,38 @@ import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMembe
import { Favorite } from '@/favorites/types/Favorite';
import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
export const useFavorites = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState());
const favoriteObjectNameSingular = 'favorite';
const { objectMetadataItem: favoriteObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: favoriteObjectNameSingular,
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const { deleteOneRecord } = useDeleteOneRecord({
objectNameSingular: favoriteObjectNameSingular,
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const { updateOneRecord: updateOneFavorite } = useUpdateOneRecord({
objectNameSingular: favoriteObjectNameSingular,
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const { createOneRecord: createOneFavorite } = useCreateOneRecord({
objectNameSingular: favoriteObjectNameSingular,
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const { records: favorites } = useFindManyRecords<Favorite>({
objectNameSingular: favoriteObjectNameSingular,
});
const { records: favorites } = usePrefetchedData<Favorite>(
PrefetchKey.AllFavorites,
);
const favoriteRelationFieldMetadataItems = useMemo(
() =>

View File

@ -1,37 +1,19 @@
import { useLocation, useNavigate } from 'react-router-dom';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { QueryMethodName } from '@/object-metadata/types/QueryMethodName';
import { useCachedRootQuery } from '@/object-record/cache/hooks/useCachedRootQuery';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { GraphQLView } from '@/views/types/GraphQLView';
export const ObjectMetadataNavItems = () => {
const { activeObjectMetadataItems, findObjectMetadataItemByNamePlural } =
useObjectMetadataItemForSettings();
const { activeObjectMetadataItems } = useObjectMetadataItemForSettings();
const navigate = useNavigate();
const { getIcon } = useIcons();
const currentPath = useLocation().pathname;
const viewObjectMetadataItem = findObjectMetadataItemByNamePlural('views');
const { cachedRootQuery } = useCachedRootQuery({
objectMetadataItem: viewObjectMetadataItem,
queryMethodName: QueryMethodName.FindMany,
});
const { records } = useFindManyRecords({
skip: cachedRootQuery?.views,
objectNameSingular: CoreObjectNameSingular.View,
useRecordsWithoutConnection: true,
});
const views =
records.length > 0
? records
: cachedRootQuery?.views?.edges?.map((edge: any) => edge?.node);
const { records } = usePrefetchedData<GraphQLView>(PrefetchKey.AllViews);
return (
<>
@ -63,7 +45,7 @@ export const ObjectMetadataNavItems = () => {
: -1;
}),
].map((objectMetadataItem) => {
const viewId = views?.find(
const viewId = records?.find(
(view: any) => view?.objectMetadataId === objectMetadataItem.id,
)?.id;

View File

@ -11,7 +11,7 @@ export const mapObjectMetadataToGraphQLQuery = ({
eagerLoadedRelations,
}: {
objectMetadataItems: ObjectMetadataItem[];
objectMetadataItem: Pick<ObjectMetadataItem, 'fields'>;
objectMetadataItem: Pick<ObjectMetadataItem, 'nameSingular' | 'fields'>;
depth?: number;
eagerLoadedRelations?: Record<string, any>;
}): any => {

View File

@ -1,47 +0,0 @@
import { useApolloClient } from '@apollo/client/react/hooks/useApolloClient';
import gql from 'graphql-tag';
import { useRecoilValue } from 'recoil';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { QueryMethodName } from '@/object-metadata/types/QueryMethodName';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
export const useCachedRootQuery = ({
objectMetadataItem,
queryMethodName,
}: {
objectMetadataItem: ObjectMetadataItem | undefined;
queryMethodName: QueryMethodName;
}) => {
const apolloClient = useApolloClient();
const objectMetadataItems = useRecoilValue(objectMetadataItemsState());
if (!objectMetadataItem) {
return { cachedRootQuery: null };
}
const cacheReadFragment = gql`
fragment RootQuery on Query {
${
QueryMethodName.FindMany === queryMethodName
? objectMetadataItem.namePlural
: objectMetadataItem.nameSingular
}
${QueryMethodName.FindMany === queryMethodName ? '{ edges { node ' : ''}
${mapObjectMetadataToGraphQLQuery({
objectMetadataItems,
objectMetadataItem,
depth: 0,
})}
${QueryMethodName.FindMany === queryMethodName ? '}}' : ''}
}
`;
const cachedRootQuery = apolloClient.readFragment({
id: 'ROOT_QUERY',
fragment: cacheReadFragment,
});
return { cachedRootQuery };
};

View File

@ -10,7 +10,10 @@ import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQu
export const useUpsertFindManyRecordsQueryInCache = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
objectMetadataItem: Pick<
ObjectMetadataItem,
'fields' | 'namePlural' | 'nameSingular'
>;
}) => {
const apolloClient = useApolloClient();

View File

@ -1,5 +1,6 @@
import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
import { getNodeTypename } from '@/object-record/cache/utils/getNodeTypename';
import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
@ -10,11 +11,26 @@ export const getRecordEdgeFromRecord = <T extends ObjectRecord>({
objectNameSingular: string;
record: T;
}) => {
const nestedRecord = Object.fromEntries(
Object.entries(record).map(([key, value]) => {
if (Array.isArray(value)) {
return [
key,
getRecordConnectionFromRecords({
objectNameSingular: key,
records: value as ObjectRecord[],
}),
];
}
return [key, value];
}),
) as T; // Todo fix typing once we have investigated apollo edges / nodes removal
return {
__typename: getEdgeTypename({ objectNameSingular }),
node: {
__typename: getNodeTypename({ objectNameSingular }),
...record,
...nestedRecord,
},
cursor: '',
} as ObjectRecordEdge<T>;

View File

@ -1,5 +1,7 @@
import { gql } from '@apollo/client';
import { useRecoilValue } from 'recoil';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
@ -12,6 +14,7 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
objectMetadataItems: ObjectMetadataItem[];
depth?: number;
}) => {
const allObjectMetadataItems = useRecoilValue(objectMetadataItemsState());
const capitalizedObjectNameSingulars = objectMetadataItems.map(
({ nameSingular }) => capitalize(nameSingular),
);
@ -44,7 +47,7 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
const limitPerMetadataItemArray = capitalizedObjectNameSingulars
.map(
(capitalizedObjectNameSingular) =>
`$limit${capitalizedObjectNameSingular}: Float = 5`,
`$limit${capitalizedObjectNameSingular}: Float`,
)
.join(', ');
@ -69,7 +72,7 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
)}){
edges {
node ${mapObjectMetadataToGraphQLQuery({
objectMetadataItems,
objectMetadataItems: allObjectMetadataItems,
objectMetadataItem,
depth,
})}
@ -80,6 +83,7 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
startCursor
endCursor
}
totalCount
}`,
)
.join('\n')}

View File

@ -0,0 +1,7 @@
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
export type QueryKey = {
objectNameSingular: string;
variables: ObjectRecordQueryVariables;
depth: number;
};

View File

@ -13,7 +13,7 @@ const query = gql`
$filterNameSingular: NameSingularFilterInput
$orderByNameSingular: NameSingularOrderByInput
$lastCursorNameSingular: String
$limitNameSingular: Float = 5
$limitNameSingular: Float
) {
namePlural(
filter: $filterNameSingular
@ -33,6 +33,7 @@ const query = gql`
startCursor
endCursor
}
totalCount
}
}
`;

View File

@ -0,0 +1,12 @@
import React from 'react';
import { PrefetchRunQueriesEffect } from '@/prefetch/components/PrefetchRunQueriesEffect';
export const PrefetchDataProvider = ({ children }: React.PropsWithChildren) => {
return (
<>
<PrefetchRunQueriesEffect />
{children}
</>
);
};

View File

@ -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 <></>;
};

View File

@ -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,
};

View File

@ -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,
};
};

View File

@ -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,
};
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
});

View File

@ -0,0 +1,4 @@
export enum PrefetchKey {
AllViews = 'ALL_VIEWS',
AllFavorites = 'ALL_FAVORITES',
}

View File

@ -2,8 +2,8 @@ import { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { useViewBar } from '@/views/hooks/useViewBar';
import { GraphQLView } from '@/views/types/GraphQLView';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@ -31,25 +31,26 @@ export const ViewBarEffect = () => {
const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState);
const setCurrentViewId = useSetRecoilState(currentViewIdState);
const { records: newViews } = useFindManyRecords<GraphQLView>({
skip: !viewObjectMetadataId,
objectNameSingular: CoreObjectNameSingular.View,
filter: {
objectMetadataId: { eq: viewObjectMetadataId },
},
useRecordsWithoutConnection: true,
});
const { records: newViews } = usePrefetchedData<GraphQLView>(
PrefetchKey.AllViews,
);
const newViewsOnCurrentObject = newViews.filter(
(view) => view.objectMetadataId === viewObjectMetadataId,
);
useEffect(() => {
if (!newViews.length) return;
if (!newViewsOnCurrentObject.length) return;
if (!isDeeplyEqual(views, newViews)) {
setViews(newViews);
if (!isDeeplyEqual(views, newViewsOnCurrentObject)) {
setViews(newViewsOnCurrentObject);
}
const currentView =
newViews.find((view) => view.id === currentViewIdFromUrl) ??
newViews[0] ??
newViewsOnCurrentObject.find(
(view) => view.id === currentViewIdFromUrl,
) ??
newViewsOnCurrentObject[0] ??
null;
if (isUndefinedOrNull(currentView)) return;
@ -69,17 +70,17 @@ export const ViewBarEffect = () => {
loadViewFields,
loadViewFilters,
loadViewSorts,
newViews,
newViewsOnCurrentObject,
setCurrentViewId,
setViews,
views,
]);
useEffect(() => {
if (!currentViewIdFromUrl || !newViews.length) return;
if (!currentViewIdFromUrl || !newViewsOnCurrentObject.length) return;
loadView(currentViewIdFromUrl);
}, [currentViewIdFromUrl, loadView, newViews]);
}, [currentViewIdFromUrl, loadView, newViewsOnCurrentObject]);
return <></>;
};