fix(front): duplicate junction chip after Add New in relation picker (#23185)

Clicking Add New in a junction relation picker rendered the newly
created target twice until a page reload. The handler appended the
created junction to the source record's store field after awaiting the
mutation, but useCreateOneRecord's post-optimistic effect had already
attached it, so the same junction id ended up in the field array twice
(single row in DB). Removes the redundant manual append in both to-many
picker flows.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23185?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
neo773
2026-07-24 00:55:30 +05:30
committed by GitHub
parent 6623901eb4
commit 97d2b52a71
2 changed files with 10 additions and 49 deletions
@@ -24,7 +24,6 @@ import { multipleRecordPickerPickableMorphItemsComponentState } from '@/object-r
import { multipleRecordPickerSearchFilterComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerSearchFilterComponentState';
import { multipleRecordPickerSearchableObjectMetadataItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerSearchableObjectMetadataItemsComponentState';
import { getRecordFieldCardRelationPickerDropdownId } from '@/object-record/record-show/utils/getRecordFieldCardRelationPickerDropdownId';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { buildRecordLabelPayload } from '@/object-record/utils/buildRecordLabelPayload';
@@ -308,33 +307,15 @@ export const RecordDetailRelationSectionDropdownToMany = ({
await createTargetRecord(targetPayload);
const newJunctionId = v4();
const createdJunction = await createJunctionRecord({
id: newJunctionId,
// The junction is already attached to the source record's field by
// useCreateOneRecord's post-optimistic effect; appending it here as
// well would render the same target twice until a reload
await createJunctionRecord({
id: v4(),
[sourceJoinColumnName]: recordId,
[targetJoinColumnName]: newTargetId,
});
if (isDefined(createdJunction)) {
store.set(
recordStoreFamilyState.atomFamily(recordId),
(currentRecord: ObjectRecord | null | undefined) => {
if (!isDefined(currentRecord)) {
return currentRecord;
}
const currentFieldValue = currentRecord[fieldName];
const updatedJunctionRecords = Array.isArray(currentFieldValue)
? [...currentFieldValue, createdJunction]
: [createdJunction];
return {
...currentRecord,
[fieldName]: updatedJunctionRecords,
} as ObjectRecord;
},
);
}
updatePickerState(newTargetId, junctionTargetObjectMetadata.id);
return;
}
@@ -28,8 +28,6 @@ import { hasJunctionConfig } from '@/object-record/record-field/ui/utils/junctio
import { MultipleRecordPicker } from '@/object-record/record-picker/multiple-record-picker/components/MultipleRecordPicker';
import { useMultipleRecordPickerPerformSearch } from '@/object-record/record-picker/multiple-record-picker/hooks/useMultipleRecordPickerPerformSearch';
import { multipleRecordPickerPickableMorphItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerPickableMorphItemsComponentState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { buildRecordLabelPayload } from '@/object-record/utils/buildRecordLabelPayload';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
@@ -238,33 +236,15 @@ export const RelationOneToManyFieldInput = () => {
await createTargetRecord(targetPayload);
const newJunctionId = v4();
const createdJunction = await createJunctionRecord({
id: newJunctionId,
// The junction is already attached to the source record's field by
// useCreateOneRecord's post-optimistic effect; appending it here as
// well would render the same target twice until a reload
await createJunctionRecord({
id: v4(),
[sourceJoinColumnName]: recordId,
[targetJoinColumnName]: newTargetId,
});
if (isDefined(createdJunction)) {
store.set(
recordStoreFamilyState.atomFamily(recordId),
(currentRecord: ObjectRecord | null | undefined) => {
if (!isDefined(currentRecord)) {
return currentRecord;
}
const currentFieldValue = currentRecord[fieldName];
const updatedJunctionRecords = Array.isArray(currentFieldValue)
? [...currentFieldValue, createdJunction]
: [createdJunction];
return {
...currentRecord,
[fieldName]: updatedJunctionRecords,
} as ObjectRecord;
},
);
}
updatePickerState(newTargetId, junctionTargetObjectMetadata.id, [
junctionTargetObjectMetadata,
]);