From 51884534829f236cffce07a601dc90f4119325f1 Mon Sep 17 00:00:00 2001 From: Flavien DELANGLE Date: Wed, 20 Nov 2024 10:09:27 +0100 Subject: [PATCH] [pickers] Always use `props.value` when it changes (#15490) --- .../tests/field.DesktopDatePicker.test.tsx | 42 +++++++++++++++++++ .../hooks/usePicker/usePickerValue.ts | 14 ++----- .../hooks/usePicker/usePickerValue.types.ts | 2 +- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/packages/x-date-pickers/src/DesktopDatePicker/tests/field.DesktopDatePicker.test.tsx b/packages/x-date-pickers/src/DesktopDatePicker/tests/field.DesktopDatePicker.test.tsx index b3a986e7e1ed..04ddd9c3b82b 100644 --- a/packages/x-date-pickers/src/DesktopDatePicker/tests/field.DesktopDatePicker.test.tsx +++ b/packages/x-date-pickers/src/DesktopDatePicker/tests/field.DesktopDatePicker.test.tsx @@ -1,5 +1,6 @@ import { fireEvent } from '@mui/internal-test-utils'; import { DesktopDatePicker, DesktopDatePickerProps } from '@mui/x-date-pickers/DesktopDatePicker'; +import { fireUserEvent } from 'test/utils/fireUserEvent'; import { createPickerRenderer, buildFieldInteractions, @@ -98,6 +99,47 @@ describe(' - Field', () => { testFormat({ views: ['year', 'month', 'day'] }, 'MM/DD/YYYY'); testFormat({ views: ['year', 'day'] }, 'MM/DD/YYYY'); }); + + it('should allow to set the value to its previous valid value using props.value', () => { + // Test with accessible DOM structure + let view = renderWithProps( + { + enableAccessibleFieldDOMStructure: true as const, + value: adapterToUse.date('2022-10-31'), + }, + { componentFamily: 'picker' }, + ); + + view.selectSection('month'); + expectFieldValueV7(view.getSectionsContainer(), '10/31/2022'); + + view.pressKey(0, 'ArrowUp'); + expectFieldValueV7(view.getSectionsContainer(), '11/31/2022'); + + view.setProps({ value: adapterToUse.date('2022-10-31') }); + expectFieldValueV7(view.getSectionsContainer(), '10/31/2022'); + + view.unmount(); + + // Test with non-accessible DOM structure + view = renderWithProps( + { + enableAccessibleFieldDOMStructure: false as const, + value: adapterToUse.date('2022-10-31'), + }, + { componentFamily: 'picker' }, + ); + + const input = getTextbox(); + view.selectSection('month'); + expectFieldValueV6(input, '10/31/2022'); + + fireUserEvent.keyPress(input, { key: 'ArrowUp' }); + expectFieldValueV6(input, '11/31/2022'); + + view.setProps({ value: adapterToUse.date('2022-10-31') }); + expectFieldValueV6(input, '10/31/2022'); + }); }); describe('slots: field', () => { diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts index 0528eae7f27b..0f123bc6e9a6 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts @@ -236,7 +236,7 @@ export const usePickerValue = < draft: initialValue, lastPublishedValue: initialValue, lastCommittedValue: initialValue, - lastControlledValue: inValueWithTimezoneToRender, + lastControlledValue: inValueWithoutRenderTimezone, hasBeenModifiedSinceMount: false, }; }); @@ -315,15 +315,7 @@ export const usePickerValue = < } }); - if ( - inValueWithTimezoneToRender !== undefined && - (dateState.lastControlledValue === undefined || - !valueManager.areValuesEqual( - utils, - dateState.lastControlledValue, - inValueWithTimezoneToRender, - )) - ) { + if (dateState.lastControlledValue !== inValueWithoutRenderTimezone) { const isUpdateComingFromPicker = valueManager.areValuesEqual( utils, dateState.draft, @@ -332,7 +324,7 @@ export const usePickerValue = < setDateState((prev) => ({ ...prev, - lastControlledValue: inValueWithTimezoneToRender, + lastControlledValue: inValueWithoutRenderTimezone, ...(isUpdateComingFromPicker ? {} : { diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts index 1ebdbeb94b77..8741bd6838ee 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts @@ -142,7 +142,7 @@ export interface UsePickerValueState { */ lastCommittedValue: TValue; /** - * Last value passed with `props.value`. + * Last value passed to `props.value`. * Used to update the `draft` value whenever the `value` prop changes. */ lastControlledValue: TValue | undefined;