Skip to content

Commit

Permalink
Refacto views (#10272)
Browse files Browse the repository at this point in the history
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 #10253

---------

Co-authored-by: Lucas Bordeau <[email protected]>
Co-authored-by: prastoin <[email protected]>
  • Loading branch information
3 people authored Feb 18, 2025
1 parent 103dff4 commit fb42046
Show file tree
Hide file tree
Showing 125 changed files with 1,607 additions and 1,582 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,17 @@ import { RegisterRecordActionEffect } from '@/action-menu/actions/record-actions
import { WorkflowRunRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/workflow-run-record-actions/components/WorkflowRunRecordActionMenuEntrySetter';
import { getActionConfig } from '@/action-menu/actions/utils/getActionConfig';
import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
import { FeatureFlagKey } from '~/generated/graphql';

export const RecordActionMenuEntriesSetter = () => {
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
);

const objectMetadataItems = useRecoilValue(objectMetadataItemsState);

const objectMetadataItem = objectMetadataItems.find(
(item) => item.id === contextStoreCurrentObjectMetadataId,
const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
);

const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
Expand All @@ -39,10 +31,7 @@ export const RecordActionMenuEntriesSetter = () => {
FeatureFlagKey.IsCommandMenuV2Enabled,
);

if (
!isDefined(contextStoreCurrentObjectMetadataId) ||
!isDefined(objectMetadataItem)
) {
if (!isDefined(contextStoreCurrentObjectMetadataItem)) {
return null;
}

Expand All @@ -52,7 +41,7 @@ export const RecordActionMenuEntriesSetter = () => {
);

const actionConfig = getActionConfig(
objectMetadataItem,
contextStoreCurrentObjectMetadataItem,
isCommandMenuV2Enabled,
);

Expand All @@ -68,15 +57,15 @@ export const RecordActionMenuEntriesSetter = () => {
<RegisterRecordActionEffect
key={action.key}
action={action}
objectMetadataItem={objectMetadataItem}
objectMetadataItem={contextStoreCurrentObjectMetadataItem}
/>
))}

{isWorkflowEnabled &&
contextStoreTargetedRecordsRule?.mode === 'selection' &&
contextStoreTargetedRecordsRule?.selectedRecordIds.length === 1 && (
<WorkflowRunRecordActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
objectMetadataItem={contextStoreCurrentObjectMetadataItem}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { RecordIndexActionMenuButtons } from '@/action-menu/components/RecordInd
import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';

import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { isRecordIndexLoadMoreLockedComponentState } from '@/object-record/record-index/states/isRecordIndexLoadMoreLockedComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
Expand All @@ -18,8 +17,8 @@ import { useIsMobile } from 'twenty-ui';
import { FeatureFlagKey } from '~/generated/graphql';

export const RecordIndexActionMenu = ({ indexId }: { indexId: string }) => {
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
);

const isCommandMenuV2Enabled = useIsFeatureEnabled(
Expand All @@ -39,7 +38,7 @@ export const RecordIndexActionMenu = ({ indexId }: { indexId: string }) => {

return (
<>
{contextStoreCurrentObjectMetadataId && (
{contextStoreCurrentObjectMetadataItem && (
<ActionMenuContext.Provider
value={{
isInRightDrawer: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { RunWorkflowRecordAgnosticActionMenuEntriesSetter } from '@/action-menu/
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
import { RecordShowActionMenuButtons } from '@/action-menu/components/RecordShowActionMenuButtons';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';

import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
Expand All @@ -26,8 +25,8 @@ export const RecordShowActionMenu = ({
objectNameSingular: string;
handleFavoriteButtonClick: () => void;
}) => {
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
);

const isCommandMenuV2Enabled = useIsFeatureEnabled(
Expand All @@ -42,7 +41,7 @@ export const RecordShowActionMenu = ({

return (
<>
{contextStoreCurrentObjectMetadataId && (
{contextStoreCurrentObjectMetadataItem && (
<ActionMenuContext.Provider
value={{
isInRightDrawer: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { RunWorkflowRecordAgnosticActionMenuEntriesSetter } from '@/action-menu/
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
import { RightDrawerActionMenuDropdown } from '@/action-menu/components/RightDrawerActionMenuDropdown';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';

import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FeatureFlagKey } from '~/generated-metadata/graphql';

export const RecordShowRightDrawerActionMenu = () => {
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
);

const isWorkflowEnabled = useIsFeatureEnabled(
Expand All @@ -21,7 +20,7 @@ export const RecordShowRightDrawerActionMenu = () => {

return (
<>
{contextStoreCurrentObjectMetadataId && (
{contextStoreCurrentObjectMetadataItem && (
<ActionMenuContext.Provider value={{ isInRightDrawer: true }}>
<RightDrawerActionMenuDropdown />
<ActionMenuConfirmationModals />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const triggerCreateRecordsOptimisticEffect = ({
});

cache.modify<StoreObject>({
broadcast: false,
fields: {
[objectMetadataItem.namePlural]: (
rootQueryCachedResponse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ export const AppRouterProviders = () => {
</DialogManager>
</DialogManagerScope>
</SnackBarProvider>
<MainContextStoreProvider />
</PrefetchDataProvider>
</ObjectMetadataItemsGater>
<PageChangeEffect />
<MainContextStoreProvider />
</ObjectMetadataItemsProvider>
</ApolloMetadataClientProvider>
</AuthProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import { RESET_CONTEXT_TO_SELECTION } from '@/command-menu/constants/ResetContex
import { useMatchingCommandMenuCommands } from '@/command-menu/hooks/useMatchingCommandMenuCommands';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { Command } from '@/command-menu/types/Command';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useLingui } from '@lingui/react/macro';
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';

Expand Down Expand Up @@ -50,23 +48,19 @@ export const CommandMenu = () => {
)
.filter(isDefined);

const previousContextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
'command-menu-previous',
);

const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const currentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
);
const previousContextStoreCurrentObjectMetadataItem =
useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
'command-menu-previous',
);

const currentObjectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) => objectMetadataItem.id === currentObjectMetadataId,
const currentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
);

const selectableItemIds = selectableItems.map((item) => item.id);

if (isNonEmptyString(previousContextStoreCurrentObjectMetadataId)) {
if (isDefined(previousContextStoreCurrentObjectMetadataItem)) {
selectableItemIds.unshift(RESET_CONTEXT_TO_SELECTION);
}

Expand Down Expand Up @@ -103,7 +97,7 @@ export const CommandMenu = () => {
selectableItemIds={selectableItemIds}
noResults={noResults}
>
{isNonEmptyString(previousContextStoreCurrentObjectMetadataId) && (
{isDefined(previousContextStoreCurrentObjectMetadataItem) && (
<CommandGroup heading={t`Context`}>
<SelectableItem itemId={RESET_CONTEXT_TO_SELECTION}>
<ResetContextToSelectionCommandButton />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { commandMenuNavigationStackState } from '@/command-menu/states/commandMe
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useTheme } from '@emotion/react';
Expand Down Expand Up @@ -96,8 +96,8 @@ export const CommandMenuTopBar = () => {

const { closeCommandMenu, goBackFromCommandMenu } = useCommandMenu();

const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
);

const commandMenuPage = useRecoilValue(commandMenuPageState);
Expand Down Expand Up @@ -137,11 +137,11 @@ export const CommandMenuTopBar = () => {
testId="command-menu-go-back-button"
/>
)}
{isDefined(contextStoreCurrentObjectMetadataId) &&
{isDefined(contextStoreCurrentObjectMetadataItem) &&
commandMenuPage !== CommandMenuPages.SearchRecords ? (
<CommandMenuContextChipGroupsWithRecordSelection
contextChips={contextChips}
objectMetadataItemId={contextStoreCurrentObjectMetadataId}
objectMetadataItemId={contextStoreCurrentObjectMetadataItem.id}
/>
) : (
<CommandMenuContextChipGroups contextChips={contextChips} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CommandMenuContextRecordChip } from '@/command-menu/components/CommandM
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { RESET_CONTEXT_TO_SELECTION } from '@/command-menu/constants/ResetContextToSelection';
import { useResetPreviousCommandMenuContext } from '@/command-menu/hooks/useResetPreviousCommandMenuContext';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
Expand All @@ -17,16 +17,16 @@ export const ResetContextToSelectionCommandButton = () => {
'command-menu-previous',
);

const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
'command-menu-previous',
);

const objectMetadataItems = useRecoilValue(objectMetadataItemsState);

const objectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) =>
objectMetadataItem.id === contextStoreCurrentObjectMetadataId,
objectMetadataItem.id === contextStoreCurrentObjectMetadataItem?.id,
);

const { resetPreviousCommandMenuContext } =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
Expand All @@ -17,19 +17,19 @@ export const useCopyContextStoreStates = () => {
instanceIdToCopyFrom: string;
instanceIdToCopyTo: string;
}) => {
const contextStoreCurrentObjectMetadataId = snapshot
const contextStoreCurrentObjectMetadataItem = snapshot
.getLoadable(
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
contextStoreCurrentObjectMetadataItemComponentState.atomFamily({
instanceId: instanceIdToCopyFrom,
}),
)
.getValue();

set(
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
contextStoreCurrentObjectMetadataItemComponentState.atomFamily({
instanceId: instanceIdToCopyTo,
}),
contextStoreCurrentObjectMetadataId,
contextStoreCurrentObjectMetadataItem,
);

const contextStoreTargetedRecordsRule = snapshot
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
Expand All @@ -11,10 +11,10 @@ export const useResetContextStoreStates = () => {
const resetContextStoreStates = useRecoilCallback(({ set }) => {
return (instanceId: string) => {
set(
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
contextStoreCurrentObjectMetadataItemComponentState.atomFamily({
instanceId,
}),
null,
undefined,
);

set(
Expand Down Expand Up @@ -45,7 +45,7 @@ export const useResetContextStoreStates = () => {
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId,
}),
null,
undefined,
);

set(
Expand Down

This file was deleted.

Loading

0 comments on commit fb42046

Please sign in to comment.