From 5b4cb4bd2c50c2983862ad96f212774cf34379ed Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 17 Feb 2025 17:27:28 +0100 Subject: [PATCH] Simplify last visited (#10259) In this PR, I'm simplifying the lastVisitedView / Object logic: - removing fallback logic as it's not useful - splitting hooks into smaller hooks (to avoir re-renders) - removing componentState on those states that are global --- .../components/MainContextStoreProvider.tsx | 1 + .../MainContextStoreProviderEffect.tsx | 38 ++++------ .../hooks/useDefaultHomePagePath.ts | 7 +- .../hooks/useLastVisitedObjectMetadataItem.ts | 70 ------------------- .../navigation/hooks/useLastVisitedView.ts | 49 ++----------- .../navigation/hooks/useOpenSettings.ts | 6 +- .../useSetLastVisitedObjectMetadataId.ts | 35 ++++++++++ ...tVisitedViewForObjectMetadataNamePlural.ts | 63 +++++++++++++++++ .../lastVisitedObjectMetadataItemIdState.ts | 7 +- ...stVisitedViewPerObjectMetadataItemState.ts | 16 +++-- ...isitedObjectMetadataItemIdStateSelector.ts | 24 ------- ...dViewPerObjectMetadataItemStateSelector.ts | 34 --------- ...igationDrawerItemForObjectMetadataItem.tsx | 35 +++++++--- .../hooks/useFilterableFieldMetadataItems.ts | 14 ++++ ...eFieldMetadataItemsInRecordIndexContext.ts | 9 +-- .../components/RecordIndexContainer.tsx | 7 +- .../prefetch/hooks/useLazyPrefetchData.ts | 30 ++++++++ .../components/SettingsObjectSummaryCard.tsx | 8 --- .../components/tabs/ObjectSettings.tsx | 27 +------ .../components/ViewBarRecordFilterEffect.tsx | 34 +++++++-- ...eApplyViewFiltersToCurrentRecordFilters.ts | 10 ++- .../pages/object-record/RecordIndexPage.tsx | 3 +- 22 files changed, 249 insertions(+), 278 deletions(-) delete mode 100644 packages/twenty-front/src/modules/navigation/hooks/useLastVisitedObjectMetadataItem.ts create mode 100644 packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedObjectMetadataId.ts create mode 100644 packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts delete mode 100644 packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedObjectMetadataItemIdStateSelector.ts delete mode 100644 packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedViewPerObjectMetadataItemStateSelector.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItems.ts create mode 100644 packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx index ff78e6127..5ca07b30b 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx @@ -48,6 +48,7 @@ export const MainContextStoreProvider = () => { const [searchParams] = useSearchParams(); const viewIdQueryParam = searchParams.get('viewId'); + // Todo: this is triggering a lot of re-renders as we update the viewFields, we should introduce a state here const { records: views } = usePrefetchedData(PrefetchKey.AllViews); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx index a8626f4b7..28a634a72 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx @@ -1,8 +1,8 @@ import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; -import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem'; -import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; +import { useSetLastVisitedObjectMetadataId } from '@/navigation/hooks/useSetLastVisitedObjectMetadataId'; +import { useSetLastVisitedViewForObjectMetadataNamePlural } from '@/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; import { useEffect } from 'react'; @@ -22,15 +22,11 @@ export const MainContextStoreProviderEffect = ({ setMainContextStoreComponentInstanceId, ] = useRecoilState(mainContextStoreComponentInstanceIdState); - const { getLastVisitedViewIdFromObjectNamePlural, setLastVisitedView } = - useLastVisitedView(); + const { setLastVisitedViewForObjectMetadataNamePlural } = + useSetLastVisitedViewForObjectMetadataNamePlural(); - const { lastVisitedObjectMetadataItemId, setLastVisitedObjectMetadataItem } = - useLastVisitedObjectMetadataItem(); - - const lastVisitedViewId = getLastVisitedViewIdFromObjectNamePlural( - objectMetadataItem.namePlural, - ); + const { setLastVisitedObjectMetadataId } = + useSetLastVisitedObjectMetadataId(); const [contextStoreCurrentViewId, setContextStoreCurrentViewId] = useRecoilComponentStateV2( @@ -60,16 +56,14 @@ export const MainContextStoreProviderEffect = ({ ); } - if (viewId !== lastVisitedViewId) { - setLastVisitedView({ - objectNamePlural: objectMetadataItem.namePlural, - viewId: viewId, - }); - } + setLastVisitedViewForObjectMetadataNamePlural({ + objectNamePlural: objectMetadataItem.namePlural, + viewId: viewId, + }); - if (objectMetadataItem.id !== lastVisitedObjectMetadataItemId) { - setLastVisitedObjectMetadataItem(objectMetadataItem.namePlural); - } + setLastVisitedObjectMetadataId({ + objectMetadataItemId: objectMetadataItem.id, + }); if (contextStoreCurrentViewId !== viewId) { setContextStoreCurrentViewId(viewId); @@ -77,16 +71,14 @@ export const MainContextStoreProviderEffect = ({ }, [ contextStoreCurrentObjectMetadataId, contextStoreCurrentViewId, - lastVisitedObjectMetadataItemId, - lastVisitedViewId, mainContextStoreComponentInstanceId, mainContextStoreComponentInstanceIdToSet, objectMetadataItem, objectMetadataItem.namePlural, setContextStoreCurrentObjectMetadataId, setContextStoreCurrentViewId, - setLastVisitedObjectMetadataItem, - setLastVisitedView, + setLastVisitedObjectMetadataId, + setLastVisitedViewForObjectMetadataNamePlural, setMainContextStoreComponentInstanceId, viewId, ]); diff --git a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts index b3fa4412d..fe8d45a6c 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts @@ -1,5 +1,5 @@ import { currentUserState } from '@/auth/states/currentUserState'; -import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem'; +import { lastVisitedObjectMetadataItemIdState } from '@/navigation/states/lastVisitedObjectMetadataItemIdState'; import { ObjectPathInfo } from '@/navigation/types/ObjectPathInfo'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; @@ -16,8 +16,9 @@ export const useDefaultHomePagePath = () => { const { activeObjectMetadataItems, alphaSortedActiveObjectMetadataItems } = useFilteredObjectMetadataItems(); const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - const { lastVisitedObjectMetadataItemId } = - useLastVisitedObjectMetadataItem(); + const lastVisitedObjectMetadataItemId = useRecoilValue( + lastVisitedObjectMetadataItemIdState, + ); const getActiveObjectMetadataItemMatchingId = useCallback( (objectMetadataId: string) => { diff --git a/packages/twenty-front/src/modules/navigation/hooks/useLastVisitedObjectMetadataItem.ts b/packages/twenty-front/src/modules/navigation/hooks/useLastVisitedObjectMetadataItem.ts deleted file mode 100644 index e95fa2579..000000000 --- a/packages/twenty-front/src/modules/navigation/hooks/useLastVisitedObjectMetadataItem.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; -import { lastVisitedObjectMetadataItemIdStateSelector } from '@/navigation/states/selectors/lastVisitedObjectMetadataItemIdStateSelector'; -import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; -import { AppPath } from '@/types/AppPath'; -import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; -import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; -import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; -import { isDefined } from 'twenty-shared'; -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; -import { getAppPath } from '~/utils/navigation/getAppPath'; - -export const useLastVisitedObjectMetadataItem = () => { - const currentWorkspace = useRecoilValue(currentWorkspaceState); - const scopeId = currentWorkspace?.id ?? ''; - - const lastVisitedObjectMetadataItemIdState = extractComponentState( - lastVisitedObjectMetadataItemIdStateSelector, - scopeId, - ); - - const [lastVisitedObjectMetadataItemId, setLastVisitedObjectMetadataItemId] = - useRecoilState(lastVisitedObjectMetadataItemIdState); - - const { - findActiveObjectMetadataItemByNamePlural, - alphaSortedActiveObjectMetadataItems, - } = useFilteredObjectMetadataItems(); - - const setNavigationMemorizedUrl = useSetRecoilState( - navigationMemorizedUrlState, - ); - - const setFallbackForLastVisitedObjectMetadataItem = ( - objectMetadataItemId: string, - ) => { - const isDeactivateDefault = isDeeplyEqual( - lastVisitedObjectMetadataItemId, - objectMetadataItemId, - ); - - const [newFallbackObjectMetadataItem] = - alphaSortedActiveObjectMetadataItems.filter( - (item) => item.id !== objectMetadataItemId, - ); - - if (isDeactivateDefault) { - setLastVisitedObjectMetadataItemId(newFallbackObjectMetadataItem.id); - setNavigationMemorizedUrl( - getAppPath(AppPath.RecordIndexPage, { - objectNamePlural: newFallbackObjectMetadataItem.namePlural, - }), - ); - } - }; - - const setLastVisitedObjectMetadataItem = (objectNamePlural: string) => { - const fallbackObjectMetadataItem = - findActiveObjectMetadataItemByNamePlural(objectNamePlural); - - if (isDefined(fallbackObjectMetadataItem)) { - setLastVisitedObjectMetadataItemId(fallbackObjectMetadataItem.id); - } - }; - - return { - lastVisitedObjectMetadataItemId, - setLastVisitedObjectMetadataItem, - setFallbackForLastVisitedObjectMetadataItem, - }; -}; diff --git a/packages/twenty-front/src/modules/navigation/hooks/useLastVisitedView.ts b/packages/twenty-front/src/modules/navigation/hooks/useLastVisitedView.ts index ea6d84a31..b53bd5e14 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/useLastVisitedView.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/useLastVisitedView.ts @@ -1,54 +1,15 @@ -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; -import { lastVisitedViewPerObjectMetadataItemStateSelector } from '@/navigation/states/selectors/lastVisitedViewPerObjectMetadataItemStateSelector'; +import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; -import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; -import { useRecoilState, useRecoilValue } from 'recoil'; -import { isDefined } from 'twenty-shared'; +import { useRecoilValue } from 'recoil'; export const useLastVisitedView = () => { - const currentWorkspace = useRecoilValue(currentWorkspaceState); - const scopeId = currentWorkspace?.id ?? ''; - - const lastVisitedViewPerObjectMetadataItemState = extractComponentState( - lastVisitedViewPerObjectMetadataItemStateSelector, - scopeId, + const lastVisitedViewPerObjectMetadataItem = useRecoilValue( + lastVisitedViewPerObjectMetadataItemState, ); - const [ - lastVisitedViewPerObjectMetadataItem, - setLastVisitedViewPerObjectMetadataItem, - ] = useRecoilState(lastVisitedViewPerObjectMetadataItemState); - const { findActiveObjectMetadataItemByNamePlural } = useFilteredObjectMetadataItems(); - const setFallbackForLastVisitedView = (objectMetadataItemId: string) => { - /* ...{} allows us to pass value as undefined to remove that particular key - even though param type is of type Record */ - - setLastVisitedViewPerObjectMetadataItem({ - ...{}, - [objectMetadataItemId]: undefined, - }); - }; - - const setLastVisitedView = ({ - objectNamePlural, - viewId, - }: { - objectNamePlural: string; - viewId: string; - }) => { - const objectMetadataItem = - findActiveObjectMetadataItemByNamePlural(objectNamePlural); - - if (isDefined(objectMetadataItem)) { - setLastVisitedViewPerObjectMetadataItem({ - [objectMetadataItem.id]: viewId, - }); - } - }; - const getLastVisitedViewIdFromObjectNamePlural = ( objectNamePlural: string, ) => { @@ -65,9 +26,7 @@ export const useLastVisitedView = () => { return lastVisitedViewPerObjectMetadataItem?.[objectMetadataItemId]; }; return { - setLastVisitedView, getLastVisitedViewIdFromObjectNamePlural, getLastVisitedViewIdFromObjectMetadataItemId, - setFallbackForLastVisitedView, }; }; diff --git a/packages/twenty-front/src/modules/navigation/hooks/useOpenSettings.ts b/packages/twenty-front/src/modules/navigation/hooks/useOpenSettings.ts index 0b06f262f..92f85c1e0 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/useOpenSettings.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/useOpenSettings.ts @@ -1,12 +1,12 @@ import { currentMobileNavigationDrawerState } from '@/navigation/states/currentMobileNavigationDrawerState'; import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded'; -import { useRecoilState } from 'recoil'; +import { useSetRecoilState } from 'recoil'; export const useOpenSettingsMenu = () => { - const [, setIsNavigationDrawerExpanded] = useRecoilState( + const setIsNavigationDrawerExpanded = useSetRecoilState( isNavigationDrawerExpandedState, ); - const [, setCurrentMobileNavigationDrawer] = useRecoilState( + const setCurrentMobileNavigationDrawer = useSetRecoilState( currentMobileNavigationDrawerState, ); diff --git a/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedObjectMetadataId.ts b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedObjectMetadataId.ts new file mode 100644 index 000000000..6a9790001 --- /dev/null +++ b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedObjectMetadataId.ts @@ -0,0 +1,35 @@ +import { lastVisitedObjectMetadataItemIdState } from '@/navigation/states/lastVisitedObjectMetadataItemIdState'; +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { useRecoilCallback } from 'recoil'; +import { isDefined } from 'twenty-shared'; + +export const useSetLastVisitedObjectMetadataId = () => { + const setLastVisitedObjectMetadataId = useRecoilCallback( + ({ set, snapshot }) => + ({ objectMetadataItemId }: { objectMetadataItemId: string }) => { + const objectMetadataItems = snapshot + .getLoadable(objectMetadataItemsState) + .getValue(); + + const objectMetadataItem = objectMetadataItems.find( + (item) => item.id === objectMetadataItemId, + ); + + const lastVisitedObjectMetadataItemId = snapshot + .getLoadable(lastVisitedObjectMetadataItemIdState) + .getValue(); + + if ( + isDefined(objectMetadataItem) && + lastVisitedObjectMetadataItemId !== objectMetadataItemId + ) { + set(lastVisitedObjectMetadataItemIdState, objectMetadataItemId); + } + }, + [], + ); + + return { + setLastVisitedObjectMetadataId, + }; +}; diff --git a/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts new file mode 100644 index 000000000..762c75b27 --- /dev/null +++ b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts @@ -0,0 +1,63 @@ +import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState'; +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { useLazyPrefetchedData } from '@/prefetch/hooks/useLazyPrefetchData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { View } from '@/views/types/View'; +import { useRecoilCallback } from 'recoil'; +import { isDefined } from 'twenty-shared'; + +export const useSetLastVisitedViewForObjectMetadataNamePlural = () => { + const { records: views, findManyRecords } = useLazyPrefetchedData( + PrefetchKey.AllViews, + ); + + const setLastVisitedViewForObjectMetadataNamePlural = useRecoilCallback( + ({ set, snapshot }) => + async ({ + objectNamePlural, + viewId, + }: { + objectNamePlural: string; + viewId: string; + }) => { + await findManyRecords(); + + const view = views.find((view: View) => view.id === viewId); + + const objectMetadataItems = snapshot + .getLoadable(objectMetadataItemsState) + .getValue(); + + const objectMetadataItem = objectMetadataItems.find( + (item) => item.namePlural === objectNamePlural, + ); + + if (!isDefined(objectMetadataItem) || !isDefined(view)) { + return; + } + + if (view.objectMetadataId !== objectMetadataItem.id) { + return; + } + + const lastVisitedViewPerObjectMetadataItem = snapshot + .getLoadable(lastVisitedViewPerObjectMetadataItemState) + .getValue(); + + const lastVisitedViewId = + lastVisitedViewPerObjectMetadataItem?.[objectMetadataItem?.id]; + + if (isDefined(objectMetadataItem) && lastVisitedViewId !== viewId) { + set(lastVisitedViewPerObjectMetadataItemState, { + ...lastVisitedViewPerObjectMetadataItem, + [objectMetadataItem.id]: viewId, + }); + } + }, + [findManyRecords, views], + ); + + return { + setLastVisitedViewForObjectMetadataNamePlural, + }; +}; diff --git a/packages/twenty-front/src/modules/navigation/states/lastVisitedObjectMetadataItemIdState.ts b/packages/twenty-front/src/modules/navigation/states/lastVisitedObjectMetadataItemIdState.ts index a615fe1c7..b879581ae 100644 --- a/packages/twenty-front/src/modules/navigation/states/lastVisitedObjectMetadataItemIdState.ts +++ b/packages/twenty-front/src/modules/navigation/states/lastVisitedObjectMetadataItemIdState.ts @@ -1,10 +1,7 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createState } from 'twenty-ui'; import { localStorageEffect } from '~/utils/recoil-effects'; -export const lastVisitedObjectMetadataItemIdState = createComponentState | null>({ +export const lastVisitedObjectMetadataItemIdState = createState({ key: 'lastVisitedObjectMetadataItemIdState', defaultValue: null, effects: [localStorageEffect()], diff --git a/packages/twenty-front/src/modules/navigation/states/lastVisitedViewPerObjectMetadataItemState.ts b/packages/twenty-front/src/modules/navigation/states/lastVisitedViewPerObjectMetadataItemState.ts index f8f2176b9..a22a42b21 100644 --- a/packages/twenty-front/src/modules/navigation/states/lastVisitedViewPerObjectMetadataItemState.ts +++ b/packages/twenty-front/src/modules/navigation/states/lastVisitedViewPerObjectMetadataItemState.ts @@ -1,9 +1,11 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createState } from 'twenty-ui'; import { localStorageEffect } from '~/utils/recoil-effects'; -export const lastVisitedViewPerObjectMetadataItemState = - createComponentState | null>({ - key: 'lastVisitedViewPerObjectMetadataItemState', - defaultValue: null, - effects: [localStorageEffect()], - }); +export const lastVisitedViewPerObjectMetadataItemState = createState | null>({ + key: 'lastVisitedViewPerObjectMetadataItemState', + defaultValue: null, + effects: [localStorageEffect()], +}); diff --git a/packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedObjectMetadataItemIdStateSelector.ts b/packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedObjectMetadataItemIdStateSelector.ts deleted file mode 100644 index fde862f47..000000000 --- a/packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedObjectMetadataItemIdStateSelector.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { lastVisitedObjectMetadataItemIdState } from '@/navigation/states/lastVisitedObjectMetadataItemIdState'; -import { createComponentSelector } from '@/ui/utilities/state/component-state/utils/createComponentSelector'; - -export const lastVisitedObjectMetadataItemIdStateSelector = - createComponentSelector({ - key: 'lastVisitedObjectMetadataItemIdStateSelector', - get: - ({ scopeId }: { scopeId: string }) => - ({ get }) => { - const state = get(lastVisitedObjectMetadataItemIdState({ scopeId })); - return state?.['last_visited_object'] - ? state['last_visited_object'] - : null; - }, - set: - ({ scopeId }: { scopeId: string }) => - ({ set }, newValue) => { - set(lastVisitedObjectMetadataItemIdState({ scopeId }), { - ...(typeof newValue === 'string' && { - last_visited_object: newValue, - }), - }); - }, - }); diff --git a/packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedViewPerObjectMetadataItemStateSelector.ts b/packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedViewPerObjectMetadataItemStateSelector.ts deleted file mode 100644 index 425837536..000000000 --- a/packages/twenty-front/src/modules/navigation/states/selectors/lastVisitedViewPerObjectMetadataItemStateSelector.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState'; -import { createComponentSelector } from '@/ui/utilities/state/component-state/utils/createComponentSelector'; -import { isDefined } from 'twenty-shared'; - -export const lastVisitedViewPerObjectMetadataItemStateSelector = - createComponentSelector | null>({ - key: 'lastVisitedViewPerObjectMetadataItemStateSelector', - get: - ({ scopeId }: { scopeId: string }) => - ({ get }) => { - const state = get( - lastVisitedViewPerObjectMetadataItemState({ scopeId }), - ); - - if (isDefined(state?.['last_visited_object'])) { - const { last_visited_object: _last_visited_object, ...rest } = state; - return rest; - } - - return state; - }, - set: - ({ scopeId }: { scopeId: string }) => - ({ set, get }, newValue) => { - const currentLastVisitedViewPerObjectMetadataItems = get( - lastVisitedViewPerObjectMetadataItemStateSelector({ scopeId }), - ); - - set(lastVisitedViewPerObjectMetadataItemState({ scopeId }), { - ...currentLastVisitedViewPerObjectMetadataItems, - ...newValue, - }); - }, - }); diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx index 29692d18e..b93a9df2c 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx @@ -1,4 +1,6 @@ -import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; +import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; @@ -7,9 +9,11 @@ import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/componen import { NavigationDrawerItemsCollapsableContainer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer'; import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; import { getNavigationSubItemLeftAdornment } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemLeftAdornment'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { View } from '@/views/types/View'; import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews'; import { useLocation } from 'react-router-dom'; +import { useRecoilValue } from 'recoil'; import { AnimatedExpandableContainer, useIcons } from 'twenty-ui'; import { getAppPath } from '~/utils/navigation/getAppPath'; @@ -27,20 +31,29 @@ export const NavigationDrawerItemForObjectMetadataItem = ({ views, ); - const { getIcon } = useIcons(); - const currentPath = useLocation().pathname; - const { getLastVisitedViewIdFromObjectMetadataItemId } = useLastVisitedView(); - - const lastVisitedViewId = getLastVisitedViewIdFromObjectMetadataItemId( - objectMetadataItem.id, + const mainContextStoreComponentInstanceId = useRecoilValue( + mainContextStoreComponentInstanceIdState, ); - const viewId = lastVisitedViewId ?? objectMetadataViews[0]?.id; + const contextStoreCurrentViewId = useRecoilComponentValueV2( + contextStoreCurrentViewIdComponentState, + mainContextStoreComponentInstanceId, + ); + + const lastVisitedViewPerObjectMetadataItem = useRecoilValue( + lastVisitedViewPerObjectMetadataItemState, + ); + + const lastVisitedViewId = + lastVisitedViewPerObjectMetadataItem?.[objectMetadataItem.id]; + + const { getIcon } = useIcons(); + const currentPath = useLocation().pathname; const navigationPath = getAppPath( AppPath.RecordIndexPage, { objectNamePlural: objectMetadataItem.namePlural }, - viewId ? { viewId } : undefined, + lastVisitedViewId ? { viewId: lastVisitedViewId } : undefined, ); const isActive = @@ -62,7 +75,7 @@ export const NavigationDrawerItemForObjectMetadataItem = ({ ); const selectedSubItemIndex = sortedObjectMetadataViews.findIndex( - (view) => viewId === view.id, + (view) => contextStoreCurrentViewId === view.id, ); const subItemArrayLength = sortedObjectMetadataViews.length; @@ -93,7 +106,7 @@ export const NavigationDrawerItemForObjectMetadataItem = ({ { objectNamePlural: objectMetadataItem.namePlural }, { viewId: view.id }, )} - active={viewId === view.id} + active={contextStoreCurrentViewId === view.id} subItemState={getNavigationSubItemLeftAdornment({ index, arrayLength: subItemArrayLength, diff --git a/packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItems.ts b/packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItems.ts new file mode 100644 index 000000000..244762acc --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItems.ts @@ -0,0 +1,14 @@ +import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector'; +import { useRecoilValue } from 'recoil'; + +export const useFilterableFieldMetadataItems = ( + objectMetadataItemId: string, +) => { + const filterableFieldMetadataItems = useRecoilValue( + availableFieldMetadataItemsForFilterFamilySelector({ + objectMetadataItemId, + }), + ); + + return { filterableFieldMetadataItems }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext.ts b/packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext.ts index dc977b1b5..7475f6197 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext.ts @@ -1,14 +1,11 @@ -import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector'; +import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; -import { useRecoilValue } from 'recoil'; export const useFilterableFieldMetadataItemsInRecordIndexContext = () => { const { objectMetadataItem } = useRecordIndexContextOrThrow(); - const filterableFieldMetadataItems = useRecoilValue( - availableFieldMetadataItemsForFilterFamilySelector({ - objectMetadataItemId: objectMetadataItem.id, - }), + const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( + objectMetadataItem.id, ); return { filterableFieldMetadataItems }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx index 4ec42a25f..b2c24e4d7 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx @@ -26,7 +26,7 @@ import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActio import { ContextStoreCurrentViewTypeEffect } from '@/context-store/components/ContextStoreCurrentViewTypeEffect'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; -import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext'; +import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems'; import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup'; import { RecordIndexFiltersToContextStoreEffect } from '@/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect'; import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect'; @@ -180,8 +180,9 @@ export const RecordIndexContainer = () => { contextStoreTargetedRecordsRuleComponentState, ); - const { filterableFieldMetadataItems } = - useFilterableFieldMetadataItemsInRecordIndexContext(); + const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( + objectMetadataItem.id, + ); const isCommandMenuV2Enabled = useIsFeatureEnabled( FeatureFlagKey.IsCommandMenuV2Enabled, diff --git a/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts b/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts new file mode 100644 index 000000000..3576b4fe4 --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts @@ -0,0 +1,30 @@ +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; +import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; + +export const useLazyPrefetchedData = ( + prefetchKey: PrefetchKey, + filter?: RecordGqlOperationFilter, +) => { + const { operationSignatureFactory, objectNameSingular } = + PREFETCH_CONFIG[prefetchKey]; + + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular, + }); + + const recordGqlFields = + operationSignatureFactory({ objectMetadataItem }).fields ?? filter; + const { records, findManyRecords } = useLazyFindManyRecords({ + objectNameSingular: objectNameSingular, + recordGqlFields, + }); + + return { + findManyRecords, + records, + }; +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectSummaryCard.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectSummaryCard.tsx index 5567a3bf9..2673c2e65 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectSummaryCard.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectSummaryCard.tsx @@ -9,8 +9,6 @@ import { useIcons, } from 'twenty-ui'; -import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem'; -import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard'; import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/components/SettingsDataModelObjectTypeTag'; @@ -44,12 +42,8 @@ export const SettingsObjectSummaryCard = ({ const theme = useTheme(); const { getIcon } = useIcons(); const Icon = getIcon(iconKey); - const objectMetadataItemId = objectMetadataItem.id; const { closeDropdown } = useDropdown(dropdownId); - const { setFallbackForLastVisitedView } = useLastVisitedView(); - const { setFallbackForLastVisitedObjectMetadataItem } = - useLastVisitedObjectMetadataItem(); const handleEdit = () => { onEdit(); @@ -57,8 +51,6 @@ export const SettingsObjectSummaryCard = ({ }; const handleDeactivate = () => { - setFallbackForLastVisitedObjectMetadataItem(objectMetadataItemId); - setFallbackForLastVisitedView(objectMetadataItemId); onDeactivate(); closeDropdown(); }; diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx index 171120037..0a78b2806 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx @@ -3,10 +3,8 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { zodResolver } from '@hookform/resolvers/zod'; import { FormProvider, useForm } from 'react-hook-form'; import { Button, H2Title, IconArchive, Section } from 'twenty-ui'; -import { z, ZodError } from 'zod'; +import { ZodError, z } from 'zod'; -import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem'; -import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { @@ -17,11 +15,9 @@ import { import { settingsDataModelObjectIdentifiersFormSchema } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm'; import { SettingsDataModelObjectSettingsFormCard } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectSettingsFormCard'; import { settingsUpdateObjectInputSchema } from '@/settings/data-model/validation-schemas/settingsUpdateObjectInputSchema'; -import { AppPath } from '@/types/AppPath'; import { SettingsPath } from '@/types/SettingsPath'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; -import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; import styled from '@emotion/styled'; import { useLingui } from '@lingui/react/macro'; import pick from 'lodash.pick'; @@ -29,7 +25,6 @@ import { useSetRecoilState } from 'recoil'; import { useNavigateSettings } from '~/hooks/useNavigateSettings'; import { updatedObjectNamePluralState } from '~/pages/settings/data-model/states/updatedObjectNamePluralState'; import { computeMetadataNameFromLabel } from '~/pages/settings/data-model/utils/compute-metadata-name-from-label.utils'; -import { getAppPath } from '~/utils/navigation/getAppPath'; const objectEditFormSchema = z .object({}) @@ -63,9 +58,6 @@ export const ObjectSettings = ({ objectMetadataItem }: ObjectSettingsProps) => { ); const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem(); - const { lastVisitedObjectMetadataItemId } = - useLastVisitedObjectMetadataItem(); - const { getLastVisitedViewIdFromObjectMetadataItemId } = useLastVisitedView(); const formConfig = useForm({ mode: 'onTouched', @@ -73,10 +65,6 @@ export const ObjectSettings = ({ objectMetadataItem }: ObjectSettingsProps) => { }); const { isDirty } = formConfig.formState; - const setNavigationMemorizedUrl = useSetRecoilState( - navigationMemorizedUrlState, - ); - const getUpdatePayload = ( formValues: SettingsDataModelObjectEditFormValues, ) => { @@ -143,19 +131,6 @@ export const ObjectSettings = ({ objectMetadataItem }: ObjectSettingsProps) => { formConfig.reset(undefined, { keepValues: true }); - if (lastVisitedObjectMetadataItemId === objectMetadataItem.id) { - const lastVisitedView = getLastVisitedViewIdFromObjectMetadataItemId( - objectMetadataItem.id, - ); - setNavigationMemorizedUrl( - getAppPath( - AppPath.RecordIndexPage, - { objectNamePlural: objectNamePluralForRedirection }, - { viewId: lastVisitedView }, - ), - ); - } - navigate(SettingsPath.ObjectDetail, { objectNamePlural: objectNamePluralForRedirection, }); diff --git a/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx index 6eec5272b..09c8ecd84 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx @@ -1,15 +1,18 @@ -import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext'; +import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; import { hasInitializedCurrentRecordFiltersComponentFamilyState } from '@/views/states/hasInitializedCurrentRecordFiltersComponentFamilyState'; import { View } from '@/views/types/View'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { useEffect } from 'react'; +import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; export const ViewBarRecordFilterEffect = () => { @@ -17,7 +20,20 @@ export const ViewBarRecordFilterEffect = () => { PrefetchKey.AllViews, ); - const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState); + const currentViewId = useRecoilComponentValueV2( + contextStoreCurrentViewIdComponentState, + ); + + const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataIdComponentState, + ); + + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); + + const objectMetadataItem = objectMetadataItems.find( + (objectMetadataItem) => + objectMetadataItem.id === contextStoreCurrentObjectMetadataId, + ); const [ hasInitializedCurrentRecordFilters, @@ -25,7 +41,7 @@ export const ViewBarRecordFilterEffect = () => { ] = useRecoilComponentFamilyStateV2( hasInitializedCurrentRecordFiltersComponentFamilyState, { - viewId: currentViewId, + viewId: currentViewId ?? undefined, }, ); @@ -37,13 +53,18 @@ export const ViewBarRecordFilterEffect = () => { currentRecordFiltersComponentState, ); - const { filterableFieldMetadataItems } = - useFilterableFieldMetadataItemsInRecordIndexContext(); + const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( + objectMetadataItem?.id, + ); useEffect(() => { if (isDataPrefetched && !hasInitializedCurrentRecordFilters) { const currentView = views.find((view) => view.id === currentViewId); + if (currentView?.objectMetadataId !== objectMetadataItem?.id) { + return; + } + if (isDefined(currentView)) { setCurrentRecordFilters( mapViewFiltersToFilters( @@ -63,6 +84,7 @@ export const ViewBarRecordFilterEffect = () => { currentRecordFilters, hasInitializedCurrentRecordFilters, setHasInitializedCurrentRecordFilters, + objectMetadataItem?.id, ]); return null; diff --git a/packages/twenty-front/src/modules/views/hooks/useApplyViewFiltersToCurrentRecordFilters.ts b/packages/twenty-front/src/modules/views/hooks/useApplyViewFiltersToCurrentRecordFilters.ts index 00d45118f..0bec3cb5e 100644 --- a/packages/twenty-front/src/modules/views/hooks/useApplyViewFiltersToCurrentRecordFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useApplyViewFiltersToCurrentRecordFilters.ts @@ -1,5 +1,6 @@ -import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext'; +import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { ViewFilter } from '@/views/types/ViewFilter'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; @@ -9,8 +10,11 @@ export const useApplyViewFiltersToCurrentRecordFilters = () => { currentRecordFiltersComponentState, ); - const { filterableFieldMetadataItems } = - useFilterableFieldMetadataItemsInRecordIndexContext(); + const { objectMetadataItem } = useRecordIndexContextOrThrow(); + + const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( + objectMetadataItem.id, + ); const applyViewFiltersToCurrentRecordFilters = ( viewFilters: ViewFilter[], diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index 36b7925ea..f151507dc 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -43,7 +43,8 @@ export const RecordIndexPage = () => { mainContextStoreComponentInstanceId, ); - const recordIndexId = `${objectNamePlural}-${contextStoreCurrentViewId}`; + // Todo: if we want the recordIndexId to contain the viewId, we need to remove the Effects otherwise we will have race condition on view change + const recordIndexId = `${objectNamePlural}`; const { objectNameSingular } = useObjectNameSingularFromPlural({ objectNamePlural,