From bdaff0b7e29c36e67a84b6cf57ac5bb0c1dc0ebc Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Sun, 22 Mar 2026 12:59:09 +0100 Subject: [PATCH] Fetch load more on group by (#18811) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/twentyhq/twenty/issues/18587 "Load More" in grouped record table view (aggregated view) which was broken — clicking it loaded no records and made the button disappear Root cause: the Load More button called fetchMore on a useLazyQuery that was never executed, causing Apollo to throw Invariant Violation: 'fetchMore' cannot be called before executing the query. The component now uses fetchMoreRecords from the same useQuery that powers the table data. Before https://github.com/user-attachments/assets/5266424b-7f35-4261-b7b7-9f7bc3eb8ad6 After https://github.com/user-attachments/assets/866fe7d7-720a-40c7-bb28-267b85bd98d5 --------- Co-authored-by: Charles Bochet --- ...ore.ts => useRecordIndexTableLazyQuery.ts} | 2 +- .../hooks/useRecordIndexTableQuery.ts | 19 +++++++++++++------ .../RecordTableRecordGroupSectionLoadMore.tsx | 7 +++---- ...dTableVirtualizedInitialDataLoadEffect.tsx | 4 ++-- .../useTriggerInitialRecordTableDataLoad.ts | 4 ++-- 5 files changed, 21 insertions(+), 15 deletions(-) rename packages/twenty-front/src/modules/object-record/record-index/hooks/{useRecordIndexTableFetchMore.ts => useRecordIndexTableLazyQuery.ts} (93%) diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableFetchMore.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableLazyQuery.ts similarity index 93% rename from packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableFetchMore.ts rename to packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableLazyQuery.ts index 73c99ab104..da937a3a9b 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableFetchMore.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableLazyQuery.ts @@ -3,7 +3,7 @@ import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRec import { useRelevantRecordsGqlFields } from '@/object-record/record-field/hooks/useRelevantRecordsGqlFields'; import { useFindManyRecordIndexTableParams } from '@/object-record/record-index/hooks/useFindManyRecordIndexTableParams'; -export const useRecordIndexTableFetchMore = (objectNameSingular: string) => { +export const useRecordIndexTableLazyQuery = (objectNameSingular: string) => { const params = useFindManyRecordIndexTableParams(objectNameSingular); const { objectMetadataItem } = useObjectMetadataItem({ diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableQuery.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableQuery.ts index 884d8b0b99..66eeb5a393 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableQuery.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexTableQuery.ts @@ -18,12 +18,18 @@ export const useRecordIndexTableQuery = (objectNameSingular: string) => { objectMetadataItem, }); - const { records, hasNextPage, queryIdentifier, loading, totalCount } = - useFindManyRecords({ - ...params, - recordGqlFields, - skip: showAuthModal, - }); + const { + records, + hasNextPage, + queryIdentifier, + loading, + totalCount, + fetchMoreRecords, + } = useFindManyRecords({ + ...params, + recordGqlFields, + skip: showAuthModal, + }); return { records: showAuthModal ? SIGN_IN_BACKGROUND_MOCK_COMPANIES : records, @@ -31,5 +37,6 @@ export const useRecordIndexTableQuery = (objectNameSingular: string) => { hasNextPage, queryIdentifier, totalCount, + fetchMoreRecords, }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSectionLoadMore.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSectionLoadMore.tsx index 57a9c6ff1b..f10488ec70 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSectionLoadMore.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSectionLoadMore.tsx @@ -1,5 +1,5 @@ import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId'; -import { useRecordIndexTableFetchMore } from '@/object-record/record-index/hooks/useRecordIndexTableFetchMore'; +import { useRecordIndexTableQuery } from '@/object-record/record-index/hooks/useRecordIndexTableQuery'; import { recordIndexHasFetchedAllRecordsByGroupComponentState } from '@/object-record/record-index/states/recordIndexHasFetchedAllRecordsByGroupComponentState'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableActionRow } from '@/object-record/record-table/record-table-row/components/RecordTableActionRow'; @@ -12,8 +12,7 @@ export const RecordTableRecordGroupSectionLoadMore = () => { const currentRecordGroupId = useCurrentRecordGroupId(); - const { fetchMoreRecordsLazy } = - useRecordIndexTableFetchMore(objectNameSingular); + const { fetchMoreRecords } = useRecordIndexTableQuery(objectNameSingular); const recordIndexHasFetchedAllRecordsByGroup = useAtomComponentFamilyStateValue( @@ -22,7 +21,7 @@ export const RecordTableRecordGroupSectionLoadMore = () => { ); const handleLoadMore = () => { - fetchMoreRecordsLazy(); + fetchMoreRecords(); }; if (recordIndexHasFetchedAllRecordsByGroup) { diff --git a/packages/twenty-front/src/modules/object-record/record-table/virtualization/components/RecordTableVirtualizedInitialDataLoadEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/virtualization/components/RecordTableVirtualizedInitialDataLoadEffect.tsx index 8762406ac2..291c1a3e36 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/virtualization/components/RecordTableVirtualizedInitialDataLoadEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/virtualization/components/RecordTableVirtualizedInitialDataLoadEffect.tsx @@ -1,4 +1,4 @@ -import { useRecordIndexTableFetchMore } from '@/object-record/record-index/hooks/useRecordIndexTableFetchMore'; +import { useRecordIndexTableLazyQuery } from '@/object-record/record-index/hooks/useRecordIndexTableLazyQuery'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; @@ -20,7 +20,7 @@ import { useEffect } from 'react'; export const RecordTableVirtualizedInitialDataLoadEffect = () => { const { recordTableId, objectNameSingular } = useRecordTableContextOrThrow(); - const { queryIdentifier } = useRecordIndexTableFetchMore(objectNameSingular); + const { queryIdentifier } = useRecordIndexTableLazyQuery(objectNameSingular); const [lastRecordTableQueryIdentifier, setLastRecordTableQueryIdentifier] = useAtomComponentState(lastRecordTableQueryIdentifierComponentState); diff --git a/packages/twenty-front/src/modules/object-record/record-table/virtualization/hooks/useTriggerInitialRecordTableDataLoad.ts b/packages/twenty-front/src/modules/object-record/record-table/virtualization/hooks/useTriggerInitialRecordTableDataLoad.ts index 8562086374..2b752f4a53 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/virtualization/hooks/useTriggerInitialRecordTableDataLoad.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/virtualization/hooks/useTriggerInitialRecordTableDataLoad.ts @@ -1,7 +1,7 @@ import { useCallback } from 'react'; import { useStore } from 'jotai'; -import { useRecordIndexTableFetchMore } from '@/object-record/record-index/hooks/useRecordIndexTableFetchMore'; +import { useRecordIndexTableLazyQuery } from '@/object-record/record-index/hooks/useRecordIndexTableLazyQuery'; import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector'; import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore'; import { RECORD_TABLE_HORIZONTAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableHorizontalScrollShadowVisibilityCssVariableName'; @@ -39,7 +39,7 @@ export const useTriggerInitialRecordTableDataLoad = () => { const showAuthModal = useShowAuthModal(); const { findManyRecordsLazy } = - useRecordIndexTableFetchMore(objectNameSingular); + useRecordIndexTableLazyQuery(objectNameSingular); const isInitializingVirtualTableDataLoadingCallbackState = useAtomComponentStateCallbackState(