From 628ba18115e2652c14adc1ffe19de830eaa92f3b Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Wed, 14 May 2025 17:40:05 +0200 Subject: [PATCH] Fix infinite loop critical bug (#12046) This PR fixes an infinite loop than happens due to a useEffect in a non deterministic manner. The fix is to put a `isDeeplyEqual()` to avoid re-rendering the useEffect if the value is the same. Fixes : https://github.com/twentyhq/core-team-issues/issues/957 --- .../components/RecordValueSetterEffect.tsx | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-store/components/RecordValueSetterEffect.tsx b/packages/twenty-front/src/modules/object-record/record-store/components/RecordValueSetterEffect.tsx index 4a80a0cd4..b4a09b068 100644 --- a/packages/twenty-front/src/modules/object-record/record-store/components/RecordValueSetterEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-store/components/RecordValueSetterEffect.tsx @@ -1,18 +1,33 @@ import { useEffect } from 'react'; import { useRecoilValue } from 'recoil'; -import { useSetRecordValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; +import { + useRecordValue, + useSetRecordValue, +} from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; +import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; // TODO: should be optimized and put higher up export const RecordValueSetterEffect = ({ recordId }: { recordId: string }) => { - const setRecordValue = useSetRecordValue(); + const setRecordValueInContextSelector = useSetRecordValue(); - const recordValue = useRecoilValue(recordStoreFamilyState(recordId)); + const recordValueFromContextSelector = useRecordValue(recordId); + + const recordValueFromRecoil = useRecoilValue( + recordStoreFamilyState(recordId), + ); useEffect(() => { - setRecordValue(recordId, recordValue); - }, [setRecordValue, recordValue, recordId]); + if (!isDeeplyEqual(recordValueFromContextSelector, recordValueFromRecoil)) { + setRecordValueInContextSelector(recordId, recordValueFromRecoil); + } + }, [ + setRecordValueInContextSelector, + recordValueFromRecoil, + recordId, + recordValueFromContextSelector, + ]); return null; };