Removed use-context-selector completely (#12139)

This PR removes use-context-selector completely, so that any bug
associated with state synchronization between recoil and
use-context-selector disappears.

There might be a slight performance decrease on the table, but since we
have already improved the average performance per line by a lot, and
that the performance bottleneck right now is the fetch more logic and
the windowing solution we use, it is not relevant.

Also the DX has become so hindered by this parallel state logic recently
(think [cache
invalidation](https://martinfowler.com/bliki/TwoHardThings.html)), that
the main benefit we gain from this removal is the DX improvement.

Fixes https://github.com/twentyhq/twenty/issues/12123
Fixes https://github.com/twentyhq/twenty/issues/12109
This commit is contained in:
Lucas Bordeau
2025-05-20 13:35:28 +02:00
committed by GitHub
parent 9ba24b3654
commit 0553f58c52
30 changed files with 408 additions and 697 deletions

View File

@ -112,10 +112,7 @@ export const SettingsDataModelFieldPreview = ({
}}
>
{isDefined(previewRecord) ? (
<SettingsDataModelSetPreviewRecordEffect
fieldName={fieldName}
record={previewRecord}
/>
<SettingsDataModelSetPreviewRecordEffect record={previewRecord} />
) : (
<SettingsDataModelSetFieldValueEffect
recordId={recordId}

View File

@ -1,4 +1,3 @@
import { useSetRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { settingsPreviewRecordIdState } from '@/settings/data-model/fields/preview/states/settingsPreviewRecordIdState';
@ -29,7 +28,6 @@ export const SettingsDataModelSetFieldValueEffect = ({
fieldName,
}),
);
const setRecordFieldValue = useSetRecordFieldValue();
useEffect(() => {
if (
@ -37,23 +35,10 @@ export const SettingsDataModelSetFieldValueEffect = ({
!!upsertedPreviewRecord[fieldName]
) {
setFieldValue(upsertedPreviewRecord[fieldName]);
setRecordFieldValue(
recordId,
fieldName,
upsertedPreviewRecord[fieldName],
);
} else {
setFieldValue(value);
setRecordFieldValue(recordId, fieldName, value);
}
}, [
value,
setFieldValue,
setRecordFieldValue,
recordId,
fieldName,
upsertedPreviewRecord,
]);
}, [value, setFieldValue, recordId, fieldName, upsertedPreviewRecord]);
return null;
};

View File

@ -1,4 +1,3 @@
import { useSetRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { settingsPreviewRecordIdState } from '@/settings/data-model/fields/preview/states/settingsPreviewRecordIdState';
@ -7,15 +6,12 @@ import { useSetRecoilState } from 'recoil';
type SettingsDataModelSetPreviewRecordEffectProps = {
record: ObjectRecord;
fieldName: string;
};
export const SettingsDataModelSetPreviewRecordEffect = ({
record,
fieldName,
}: SettingsDataModelSetPreviewRecordEffectProps) => {
const { upsertRecords: upsertRecordsInStore } = useUpsertRecordsInStore();
const setRecordFieldValue = useSetRecordFieldValue();
const setSettingsPreviewRecordId = useSetRecoilState(
settingsPreviewRecordIdState,
@ -23,15 +19,8 @@ export const SettingsDataModelSetPreviewRecordEffect = ({
useEffect(() => {
upsertRecordsInStore([record]);
setRecordFieldValue(record.id, fieldName, record[fieldName]);
setSettingsPreviewRecordId(record.id);
}, [
record,
upsertRecordsInStore,
setRecordFieldValue,
fieldName,
setSettingsPreviewRecordId,
]);
}, [record, upsertRecordsInStore, setSettingsPreviewRecordId]);
return null;
};

View File

@ -1,16 +1,15 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { SettingsUpdateDataModelObjectAboutForm } from '@/settings/data-model/object-details/components/SettingsUpdateDataModelObjectAboutForm';
import { SettingsDataModelObjectSettingsFormCard } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectSettingsFormCard';
import { SettingsPath } from '@/types/SettingsPath';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { Button } from 'twenty-ui/input';
import { H2Title, IconArchive } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { Section } from 'twenty-ui/layout';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
type ObjectSettingsProps = {
objectMetadataItem: ObjectMetadataItem;
@ -39,43 +38,38 @@ export const ObjectSettings = ({ objectMetadataItem }: ObjectSettingsProps) => {
};
return (
<RecordFieldValueSelectorContextProvider>
<StyledContentContainer>
<StyledFormSection>
<StyledContentContainer>
<StyledFormSection>
<H2Title
title={t`About`}
description={t`Name in both singular (e.g., 'Invoice') and plural (e.g., 'Invoices') forms.`}
/>
<SettingsUpdateDataModelObjectAboutForm
objectMetadataItem={objectMetadataItem}
/>
</StyledFormSection>
<StyledFormSection>
<Section>
<H2Title
title={t`About`}
description={t`Name in both singular (e.g., 'Invoice') and plural (e.g., 'Invoices') forms.`}
title={t`Options`}
description={t`Choose the fields that will identify your records`}
/>
<SettingsUpdateDataModelObjectAboutForm
<SettingsDataModelObjectSettingsFormCard
objectMetadataItem={objectMetadataItem}
/>
</StyledFormSection>
<StyledFormSection>
<Section>
<H2Title
title={t`Options`}
description={t`Choose the fields that will identify your records`}
/>
<SettingsDataModelObjectSettingsFormCard
objectMetadataItem={objectMetadataItem}
/>
</Section>
</StyledFormSection>
<StyledFormSection>
<Section>
<H2Title
title={t`Danger zone`}
description={t`Deactivate object`}
/>
<Button
Icon={IconArchive}
title={t`Deactivate`}
size="small"
onClick={handleDisable}
/>
</Section>
</StyledFormSection>
</StyledContentContainer>
</RecordFieldValueSelectorContextProvider>
</Section>
</StyledFormSection>
<StyledFormSection>
<Section>
<H2Title title={t`Danger zone`} description={t`Deactivate object`} />
<Button
Icon={IconArchive}
title={t`Deactivate`}
size="small"
onClick={handleDisable}
/>
</Section>
</StyledFormSection>
</StyledContentContainer>
);
};