From 2b860a838c7fdf021e55108d32988f2f17dc9ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Thu, 26 Oct 2023 14:11:15 +0800 Subject: [PATCH 1/2] fix: DayJs not think invalid date is same --- src/RangePicker.tsx | 46 +++++++++++++++++--------------------- src/hooks/useValueTexts.ts | 7 ++++-- tests/loop.spec.tsx | 36 +++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 tests/loop.spec.tsx diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index be155abaf..5fafaaa32 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -1,8 +1,8 @@ import classNames from 'classnames'; import useMergedState from 'rc-util/lib/hooks/useMergedState'; +import pickAttrs from 'rc-util/lib/pickAttrs'; import raf from 'rc-util/lib/raf'; import warning from 'rc-util/lib/warning'; -import pickAttrs from 'rc-util/lib/pickAttrs'; import * as React from 'react'; import { useEffect, useRef, useState } from 'react'; import type { PickerPanelProps } from '.'; @@ -43,12 +43,12 @@ import { isSameWeek, parseValue, } from './utils/dateUtil'; +import { getClearIcon } from './utils/getClearIcon'; import getExtraFooter from './utils/getExtraFooter'; import getRanges from './utils/getRanges'; import { getValue, toArray, updateValues } from './utils/miscUtil'; import { elementsContains, getDefaultFormat, getInputSize } from './utils/uiUtil'; import { legacyPropsWarning } from './utils/warnUtil'; -import { getClearIcon } from './utils/getClearIcon'; function reorderValues( values: RangeValue, @@ -407,7 +407,7 @@ function InnerRangePicker(props: RangePickerProps) { function triggerChange( newValue: RangeValue, sourceIndex: 0 | 1, - triggerCalendarChangeOnly?: boolean, + triggerCalendarChangeOnly?: boolean, ) { let values = newValue; let startValue = getValue(values, 0); @@ -576,7 +576,7 @@ function InnerRangePicker(props: RangePickerProps) { if (delayOpen) { if (needConfirmButton) { // when in dateTime mode, switching between two date input fields will trigger onCalendarChange. - // when onBlur is triggered, the input field has already switched, + // when onBlur is triggered, the input field has already switched, // so it's necessary to obtain the value of the previous input field here. const needTriggerIndex = mergedActivePickerIndex ? 0 : 1; const selectedIndexValue = getValue(selectedValue, needTriggerIndex); @@ -712,18 +712,18 @@ function InnerRangePicker(props: RangePickerProps) { const startStr = mergedValue && mergedValue[0] ? formatValue(mergedValue[0], { - locale, - format: 'YYYYMMDDHHmmss', - generateConfig, - }) + locale, + format: 'YYYYMMDDHHmmss', + generateConfig, + }) : ''; const endStr = mergedValue && mergedValue[1] ? formatValue(mergedValue[1], { - locale, - format: 'YYYYMMDDHHmmss', - generateConfig, - }) + locale, + format: 'YYYYMMDDHHmmss', + generateConfig, + }) : ''; useEffect(() => { @@ -743,6 +743,7 @@ function InnerRangePicker(props: RangePickerProps) { } }, [mergedOpen, startValueTexts, endValueTexts]); + // Sync innerValue with control mode useEffect(() => { setSelectedValue(mergedValue); @@ -775,10 +776,7 @@ function InnerRangePicker(props: RangePickerProps) { } warning(!dateRender, `'dateRender' is deprecated. Please use 'cellRender' instead.`); warning(!monthCellRender, `'monthCellRender' is deprecated. Please use 'cellRender' instead.`); - warning( - !clearIcon, - '`clearIcon` will be removed in future. Please use `allowClear` instead.', - ); + warning(!clearIcon, '`clearIcon` will be removed in future. Please use `allowClear` instead.'); } // ============================ Private ============================ @@ -886,7 +884,7 @@ function InnerRangePicker(props: RangePickerProps) { defaultValue={ mergedActivePickerIndex === 0 ? getValue(selectedValue, 1) : getValue(selectedValue, 0) } - // defaultPickerValue={undefined} + // defaultPickerValue={undefined} /> ); @@ -1065,11 +1063,7 @@ function InnerRangePicker(props: RangePickerProps) { ); } - const mergedClearIcon: React.ReactNode = getClearIcon( - prefixCls, - allowClear, - clearIcon, - ); + const mergedClearIcon: React.ReactNode = getClearIcon(prefixCls, allowClear, clearIcon); const clearNode: React.ReactNode = ( (props: RangePickerProps) { ); - const mergedAllowClear = allowClear && ( - (getValue(mergedValue as RangeValue, 0) && !mergedDisabled[0]) || - (getValue(mergedValue as RangeValue, 1) && !mergedDisabled[1]) - ); + const mergedAllowClear = + allowClear && + ((getValue(mergedValue as RangeValue, 0) && !mergedDisabled[0]) || + (getValue(mergedValue as RangeValue, 1) && !mergedDisabled[1])); const inputSharedProps = { size: getInputSize(picker, formatList[0], generateConfig), diff --git a/src/hooks/useValueTexts.ts b/src/hooks/useValueTexts.ts index 9c185e5fe..52de6ce92 100644 --- a/src/hooks/useValueTexts.ts +++ b/src/hooks/useValueTexts.ts @@ -1,5 +1,6 @@ import useMemo from 'rc-util/lib/hooks/useMemo'; import shallowEqual from 'rc-util/lib/isEqual'; +import * as React from 'react'; import type { GenerateConfig } from '../generate'; import type { CustomFormat, Locale } from '../interface'; import { formatValue, isEqual } from '../utils/dateUtil'; @@ -13,8 +14,8 @@ export type ValueTextConfig = { export default function useValueTexts( value: DateType | null, { formatList, generateConfig, locale }: ValueTextConfig, -) { - return useMemo<[string[], string]>( +): [valueTexts: string[], firstValueText: string] { + const [texts, text] = useMemo<[string[], string]>( () => { if (!value) { return [[''], '']; @@ -45,4 +46,6 @@ export default function useValueTexts( // Not Same locale !shallowEqual(prev[2], next[2], true), ); + + return React.useMemo(() => [texts, text], [texts.join(''), text]); } diff --git a/tests/loop.spec.tsx b/tests/loop.spec.tsx new file mode 100644 index 000000000..51c2bdbbd --- /dev/null +++ b/tests/loop.spec.tsx @@ -0,0 +1,36 @@ +import { render } from '@testing-library/react'; +import dayjs from 'dayjs'; +import { resetWarned } from 'rc-util/lib/warning'; +import React from 'react'; +import dayJsGenerate from '../src/generate/dayjs'; +import zhCN from '../src/locale/zh_CN'; +import RangePicker from '../src/RangePicker'; +import { getMoment } from './util/commonUtil'; + +describe('Picker.Loop', () => { + let errorSpy; + + beforeAll(() => { + errorSpy = jest.spyOn(console, 'error').mockImplementation(() => null); + }); + + beforeEach(() => { + errorSpy.mockReset(); + resetWarned(); + global.scrollCalled = false; + jest.useFakeTimers().setSystemTime(getMoment('1990-09-03 00:00:00').valueOf()); + }); + + afterEach(() => { + jest.clearAllTimers(); + jest.useRealTimers(); + }); + + it('no loop warning', () => { + render( + , + ); + + expect(errorSpy).not.toHaveBeenCalled(); + }); +}); From 51c1b9c7b98290f129923d9b615e8d65d17bb195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Thu, 26 Oct 2023 14:11:33 +0800 Subject: [PATCH 2/2] chore: clean up --- src/RangePicker.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index 5fafaaa32..01cae0def 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -743,7 +743,6 @@ function InnerRangePicker(props: RangePickerProps) { } }, [mergedOpen, startValueTexts, endValueTexts]); - // Sync innerValue with control mode useEffect(() => { setSelectedValue(mergedValue);