瀏覽代碼

fix: fixed selected value does not show when value is controlled #2521 (#2522)

Co-authored-by: shijia.me <[email protected]>
Shi Jia 1 年之前
父節點
當前提交
a1b260fef8

+ 16 - 0
cypress/e2e/datePicker.spec.js

@@ -894,4 +894,20 @@ describe('DatePicker', () => {
         cy.get('.semi-popover .semi-datepicker-day-selected-start').contains('8');
         cy.get('.semi-popover .semi-datepicker-day-selected-end').contains('9');
     });
+
+    it('fixed selected value does not show when value is controlled', () => {
+        cy.visit('http://localhost:6006/iframe.html?args=&id=datepicker--fixed-controlled-value&viewMode=story');
+        cy.get('.semi-input').eq(0).click();
+        cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day').contains('15')
+            .then($day => {
+                $day.trigger('click');
+            });
+        cy.get('.semi-datepicker-month-grid-right .semi-datepicker-day').contains('20')
+            .then($day => {
+                $day.trigger('click');
+            });
+        cy.get('.semi-input').eq(0).click();
+        cy.get('.semi-popover .semi-datepicker-day-selected-start').contains('15');
+        cy.get('.semi-popover .semi-datepicker-day-selected-end').contains('20');
+    });
 });

+ 14 - 19
packages/semi-foundation/datePicker/foundation.ts

@@ -227,7 +227,6 @@ export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationPr
  */
 export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapter> {
 
-    clickConfirmButton: boolean;
     constructor(adapter: DatePickerAdapter) {
         super({ ...adapter });
     }
@@ -389,17 +388,12 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
      *    - date type and not multiple, close panel after select date
      *    - dateRange type, close panel after select rangeStart and rangeEnd
      *  4. click outside
-     * @param {Event} e
-     * @param {String} inputValue
-     * @param {Date[]} dates
      */
-    closePanel(e?: any, inputValue: string = null, dates?: Date[]) {
-        const { value } = this._adapter.getStates();
-        const willUpdateDates = isNullOrUndefined(dates) ? value : dates;
+    closePanel() {
         if (!this._isControlledComponent('open')) {
             this.close();
         } else {
-            this.resetInnerSelectedStates(willUpdateDates);
+            this.resetInnerSelectedStates();
         }
         this._adapter.notifyOpenChange(false);
     }
@@ -410,7 +404,8 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
     }
 
     close() {
-        this._adapter.togglePanel(false, () => this.resetInnerSelectedStates());
+        this._adapter.togglePanel(false);
+        this.resetInnerSelectedStates();
         this._adapter.unregisterClickOutSide();
     }
 
@@ -434,15 +429,16 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
     /**
      * reset cachedSelectedValue, inputValue when close panel
      */
-    resetInnerSelectedStates(willUpdateDates?: Date[]) {
-        const { value } = this._adapter.getStates();
-        const needResetCachedSelectedValue = isNullOrUndefined(willUpdateDates) || !this.isCachedSelectedValueValid(willUpdateDates) || this._adapter.needConfirm() && !this.clickConfirmButton;
-        if (needResetCachedSelectedValue) {
-            this.resetCachedSelectedValue(value);
-        }
+    resetInnerSelectedStates() {
+        // 通过 setTimeout 保证需要获取到最新的 state 状态
+        setTimeout(() => {
+            const { value, cachedSelectedValue } = this._adapter.getStates();
+            if (!isEqual(value, cachedSelectedValue)) {
+                this.resetCachedSelectedValue(value);
+            }
+        }, 0);
         this.resetFocus();
         this.clearInputValue();
-        this.clickConfirmButton = false;
     }
 
     resetFocus(e?: any) {
@@ -1016,7 +1012,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
 
         const focusRecordChecked = !needCheckFocusRecord || (needCheckFocusRecord && this._adapter.couldPanelClosed());
         if ((type === 'date' && !this._isMultiple() && closePanel) || (type === 'dateRange' && this._isRangeValueComplete(dates) && closePanel && focusRecordChecked)) {
-            this.closePanel(undefined, inputValue, dates);
+            this.closePanel();
         }
     }
 
@@ -1043,7 +1039,6 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
     }
 
     handleConfirm() {
-        this.clickConfirmButton = true;
         const { cachedSelectedValue, value } = this._adapter.getStates();
         const isRangeValueComplete = this._isRangeValueComplete(cachedSelectedValue);
         const newValue = isRangeValueComplete ? cachedSelectedValue : value;
@@ -1051,7 +1046,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
             this._adapter.updateValue(newValue);
         }
         // If the input is incomplete, the legal date of the last input is used
-        this.closePanel(undefined, undefined, newValue);
+        this.closePanel();
 
         if (isRangeValueComplete) {
             const { notifyValue, notifyDate } = this.disposeCallbackArgs(cachedSelectedValue);

+ 2 - 1
packages/semi-ui/datePicker/_story/datePicker.stories.jsx

@@ -74,7 +74,8 @@ export {
     FixedNaN,
     PresetsFunctionType,
     FixedSelectedStatus,
-    FixedControlled
+    FixedControlled,
+    FixedControlledValue
 } from './v2';
 
 

+ 21 - 0
packages/semi-ui/datePicker/_story/v2/FixedControlledValue.jsx

@@ -0,0 +1,21 @@
+import React, { useState } from 'react';
+import { DatePicker } from '@douyinfe/semi-ui';
+
+/**
+ * @see https://github.com/DouyinFE/semi-design/issues/2521
+ * 
+ * related to issue #2388
+ * @see https://github.com/DouyinFE/semi-design/pull/2388
+ */
+const App = () => {
+    const [v, setV] = useState([]);
+    const handleChange = (value) => {
+        setV(value);
+    };
+    
+    return (
+        <DatePicker value={v} type="dateRange" defaultPickerValue={['2023-10-01']} style={{ width: 260 }} onChange={handleChange} />
+    );
+};
+
+export default App;

+ 1 - 0
packages/semi-ui/datePicker/_story/v2/index.js

@@ -32,3 +32,4 @@ export { default as PresetsFunctionType } from './PresetsFunctionType';
 export { default as FixedNaN } from './FixedNaN';
 export { default as FixedSelectedStatus } from './FixedSelectedStatus';
 export { default as FixedControlled } from './FixedControlled';
+export { default as FixedControlledValue } from './FixedControlledValue';

+ 1 - 1
packages/semi-ui/datePicker/datePicker.tsx

@@ -269,7 +269,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
                     ) {
                         this.props.onClickOutSide();
                         if (!this.adapter.needConfirm()) {
-                            this.foundation.closePanel(e);
+                            this.foundation.closePanel();
                         }
                     }
                 };