Fixed show page crash with object metadata item not found (#13694)

This PR fixes a bug that appeared because of a race condition with
context store when navigating between settings page and show page.

The bug was caused because record title cell used on record show page
was trying to retrieve the object metadata item before the context store
was initialized.

I created a new hook that supports an undefined state for one render
loop, since in that case components can be rendered before the context
store is initialized.

Fixes https://github.com/twentyhq/twenty/issues/13649
This commit is contained in:
Lucas Bordeau
2025-08-06 16:41:06 +02:00
committed by GitHub
parent 3db6d49e86
commit c48d14715c
2 changed files with 31 additions and 2 deletions
@@ -0,0 +1,22 @@
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilValue } from 'recoil';
export const useContextStoreObjectMetadataItem = (
contextStoreInstanceId?: string,
) => {
const objectMetadataItemId = useRecoilComponentValue(
contextStoreCurrentObjectMetadataItemIdComponentState,
contextStoreInstanceId,
);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const objectMetadataItem = objectMetadataItems.find(
(objectMetadataItemToFind) =>
objectMetadataItemToFind.id === objectMetadataItemId,
);
return { objectMetadataItem };
};
@@ -1,4 +1,4 @@
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useContextStoreObjectMetadataItem } from '@/context-store/hooks/useContextStoreObjectMetadataItem';
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
import { useInitDraftValue } from '@/object-record/record-field/hooks/useInitDraftValue';
import { isInlineCellInEditModeFamilyState } from '@/object-record/record-inline-cell/states/isInlineCellInEditModeFamilyState';
@@ -9,6 +9,7 @@ import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePush
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
export const useRecordTitleCell = () => {
const { goBackToPreviousDropdownFocusId } =
@@ -18,7 +19,7 @@ export const useRecordTitleCell = () => {
const { removeFocusItemFromFocusStackById } =
useRemoveFocusItemFromFocusStackById();
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const { objectMetadataItem } = useContextStoreObjectMetadataItem();
const closeRecordTitleCell = useRecoilCallback(
({ set }) =>
@@ -68,6 +69,12 @@ export const useRecordTitleCell = () => {
fieldName: string;
containerType: RecordTitleCellContainerType;
}) => {
if (!isDefined(objectMetadataItem)) {
throw new Error(
'Cannot find object metadata item in openRecordTitleCell this should not happen.',
);
}
pushFocusItemToFocusStack({
focusId: getRecordFieldInputInstanceId({
recordId,