Refacto views (#10272)
In this huge (sorry!) PR: - introducing objectMetadataItem in contextStore instead of objectMetadataId which is more convenient - splitting some big hooks into smaller parts to avoid re-renders - removing Effects to avoid re-renders (especially onViewChange) - making the view prefetch separate from favorites to avoid re-renders - making the view prefetch load a state and add selectors on top of it to avoir re-renders As a result, the performance is WAY better (I suspect the favorite implementation to trigger a lot of re-renders unfortunately). However, we are still facing a random app freeze on view creation. I could not investigate the root cause. As this seems to be already there in the precedent release, we can move forward but this seems a urgent follow up to me ==> EDIT: I've found the root cause after a few ours of deep dive... an infinite loop in RecordTableNoRecordGroupBodyEffect... prastoin edit: close https://github.com/twentyhq/twenty/issues/10253 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com> Co-authored-by: prastoin <paul@twenty.com>
This commit is contained in:
@ -1,74 +1,26 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
|
||||
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
||||
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
|
||||
import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
|
||||
import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer';
|
||||
import { RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect';
|
||||
import { RecordIndexContainerContextStoreObjectMetadataEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect';
|
||||
import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader';
|
||||
import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick';
|
||||
import { PageBody } from '@/ui/layout/page/components/PageBody';
|
||||
import { RecordIndexContainerGater } from '@/object-record/record-index/components/RecordIndexContainerGater';
|
||||
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
|
||||
import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { isUndefined } from '@sniptt/guards';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { capitalize } from 'twenty-shared';
|
||||
|
||||
const StyledIndexContainer = styled.div`
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
`;
|
||||
import { isNonEmptyString, isUndefined } from '@sniptt/guards';
|
||||
|
||||
export const RecordIndexPage = () => {
|
||||
const objectNamePlural = useParams().objectNamePlural ?? '';
|
||||
|
||||
const mainContextStoreComponentInstanceId = useRecoilValue(
|
||||
mainContextStoreComponentInstanceIdState,
|
||||
);
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
mainContextStoreComponentInstanceId,
|
||||
'main-context-store',
|
||||
);
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { indexIdentifierUrl } = useHandleIndexIdentifierClick({
|
||||
objectMetadataItem,
|
||||
recordIndexId,
|
||||
});
|
||||
|
||||
const handleIndexRecordsLoaded = useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
// TODO: find a better way to reset this state ?
|
||||
set(lastShowPageRecordIdState, null);
|
||||
},
|
||||
[],
|
||||
const objectMetadataItem = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataItemComponentState,
|
||||
'main-context-store',
|
||||
);
|
||||
|
||||
if (isUndefined(contextStoreCurrentViewId)) {
|
||||
if (
|
||||
isUndefined(objectMetadataItem) ||
|
||||
!isNonEmptyString(contextStoreCurrentViewId)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -76,43 +28,10 @@ export const RecordIndexPage = () => {
|
||||
<PageContainer>
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: mainContextStoreComponentInstanceId,
|
||||
instanceId: 'main-context-store',
|
||||
}}
|
||||
>
|
||||
<RecordIndexContextProvider
|
||||
value={{
|
||||
recordIndexId,
|
||||
objectNamePlural,
|
||||
objectNameSingular,
|
||||
objectMetadataItem,
|
||||
onIndexRecordsLoaded: handleIndexRecordsLoaded,
|
||||
indexIdentifierUrl,
|
||||
}}
|
||||
>
|
||||
<RecordIndexContainerContextStoreObjectMetadataEffect />
|
||||
<ViewComponentInstanceContext.Provider
|
||||
value={{ instanceId: recordIndexId }}
|
||||
>
|
||||
<RecordFiltersComponentInstanceContext.Provider
|
||||
value={{ instanceId: recordIndexId }}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: getActionMenuIdFromRecordIndexId(recordIndexId),
|
||||
}}
|
||||
>
|
||||
<PageTitle title={`${capitalize(objectNamePlural)}`} />
|
||||
<RecordIndexPageHeader />
|
||||
<PageBody>
|
||||
<StyledIndexContainer>
|
||||
<RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect />
|
||||
<RecordIndexContainer />
|
||||
</StyledIndexContainer>
|
||||
</PageBody>
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</RecordFiltersComponentInstanceContext.Provider>
|
||||
</ViewComponentInstanceContext.Provider>
|
||||
</RecordIndexContextProvider>
|
||||
<RecordIndexContainerGater />
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
</PageContainer>
|
||||
);
|
||||
|
||||
@ -51,7 +51,7 @@ export const RecordShowPage = () => {
|
||||
value={{ instanceId: `record-show-${objectRecordId}` }}
|
||||
>
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{ instanceId: `record-show-${objectRecordId}` }}
|
||||
value={{ instanceId: `main-context-store` }}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: `record-show-${objectRecordId}` }}
|
||||
|
||||
Reference in New Issue
Block a user