Browse Source

fix: [TagInput] set value to falsely has no effect #483 (#496)

Co-authored-by: chenyuling <[email protected]>
boomboomchen 3 years ago
parent
commit
637f65314d

+ 1 - 1
content/input/taginput/index-en-US.md

@@ -434,7 +434,7 @@ class CustomRender extends React.Component {
 |style         |Inline style                                     |React.CSSProperties                                               | -        |1.19.0|
 |style         |Inline style                                     |React.CSSProperties                                               | -        |1.19.0|
 |suffix        |Suffix                                            |ReactNode                                                        |-         |1.19.0|
 |suffix        |Suffix                                            |ReactNode                                                        |-         |1.19.0|
 |validateStatus|Validate status for styling only, one of  `default`、`warning`、`error`|string                                       |`default` |1.19.0|
 |validateStatus|Validate status for styling only, one of  `default`、`warning`、`error`|string                                       |`default` |1.19.0|
-|value         |Controlled tag value                              |string[]                                                         | -        |1.19.0|
+|value         |Controlled tag value                              |string[] \| undefined                                                         | -        |1.19.0|
 |onAdd         |Callback invoked when tags are added             |(addedValue: string[]) => void                                   | -        |1.19.0|
 |onAdd         |Callback invoked when tags are added             |(addedValue: string[]) => void                                   | -        |1.19.0|
 |onBlur        |Callback invoked when input loses focus          |(e:React.MouseEvent<HTMLInputElement\>) => void                  | -        |1.19.0|
 |onBlur        |Callback invoked when input loses focus          |(e:React.MouseEvent<HTMLInputElement\>) => void                  | -        |1.19.0|
 |onChange      |Callback invoked when tags changes               |(value:string[]) => void                                         | -        |1.19.0|
 |onChange      |Callback invoked when tags changes               |(value:string[]) => void                                         | -        |1.19.0|

+ 1 - 1
content/input/taginput/index.md

@@ -434,7 +434,7 @@ class CustomRender extends React.Component {
 |style        |内联样式                                          |React.CSSProperties                         | -        |1.19.0|
 |style        |内联样式                                          |React.CSSProperties                         | -        |1.19.0|
 |suffix       |后缀标签                                           |ReactNode                      |-         |1.19.0|
 |suffix       |后缀标签                                           |ReactNode                      |-         |1.19.0|
 |validateStatus|设置校验状态样式,可选: `default`、`warning`、`error` |string                          |`default` |1.19.0|
 |validateStatus|设置校验状态样式,可选: `default`、`warning`、`error` |string                          |`default` |1.19.0|
-|value        |当前标签,配合 onChange 实现受控                     |string[]                       | -        |1.19.0|
+|value        |当前标签,配合 onChange 实现受控                     |string[] \| undefined                       | -        |1.19.0|
 |onAdd        |添加标签时的回调                                     |(addedValue: string[]) => void     | -        |1.19.0|
 |onAdd        |添加标签时的回调                                     |(addedValue: string[]) => void     | -        |1.19.0|
 |onBlur       |输入框失去焦点时的回调           |(e:React.MouseEvent<HTMLInputElement\>) => void                 | -        |1.19.0|
 |onBlur       |输入框失去焦点时的回调           |(e:React.MouseEvent<HTMLInputElement\>) => void                 | -        |1.19.0|
 |onChange     |标签变化时的回调                                     |(value:string[]) => void | -        |1.19.0|
 |onChange     |标签变化时的回调                                     |(value:string[]) => void | -        |1.19.0|

+ 46 - 0
packages/semi-ui/tagInput/__test__/tagInput.test.js

@@ -76,6 +76,28 @@ describe('TagInput', () => {
         tagInput.unmount();
         tagInput.unmount();
     });
     });
 
 
+    it('TagInput with defaultValue and value is undefined', () => {
+        const props = {
+            defaultValue: ['tiktok', 'hotsoon'],
+            value: undefined,
+        };
+        const tagInput = getTagInput(props);
+        const tags = tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`);
+        expect(tags.length).toEqual(0);
+        tagInput.unmount();
+    });
+
+    it('TagInput with defaultValue and value is null', () => {
+        const props = {
+            defaultValue: ['tiktok', 'hotsoon'],
+            value: null,
+        };
+        const tagInput = getTagInput(props);
+        const tags = tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`);
+        expect(tags.length).toEqual(0);
+        tagInput.unmount();
+    });
+
     it('TagInput with disabled', () => {
     it('TagInput with disabled', () => {
         const disabledTagInput = mount(<TagInput disabled />);
         const disabledTagInput = mount(<TagInput disabled />);
         expect(disabledTagInput.exists(`.${BASE_CLASS_PREFIX}-tagInput-disabled`)).toEqual(true);
         expect(disabledTagInput.exists(`.${BASE_CLASS_PREFIX}-tagInput-disabled`)).toEqual(true);
@@ -328,6 +350,30 @@ describe('TagInput', () => {
         expect(tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`).getDOMNode().textContent).toEqual('hotsoon');
         expect(tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`).getDOMNode().textContent).toEqual('hotsoon');
     });
     });
 
 
+    it('tagInput with set value to null  ', () => {
+        const props = {
+            value: ['tiktok']
+        };
+        const tagInput = getTagInput(props);
+        expect(tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`).getDOMNode().textContent).toEqual('tiktok');
+        tagInput.setProps({ value: null });
+        tagInput.update();
+        const tags = tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`);
+        expect(tags.length).toEqual(0);
+    });
+
+    it('tagInput with set value to null  ', () => {
+        const props = {
+            value: ['tiktok']
+        };
+        const tagInput = getTagInput(props);
+        expect(tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`).getDOMNode().textContent).toEqual('tiktok');
+        tagInput.setProps({ value: undefined });
+        tagInput.update();
+        const tags = tagInput.find(`.${BASE_CLASS_PREFIX}-tagInput-wrapper .${BASE_CLASS_PREFIX}-tag-content`);
+        expect(tags.length).toEqual(0);
+    });
+
     it('tagInput with inputValue controlled mode ', () => {
     it('tagInput with inputValue controlled mode ', () => {
         const props = {
         const props = {
             inputValue: 'abc'
             inputValue: 'abc'

+ 12 - 6
packages/semi-ui/tagInput/index.tsx

@@ -55,7 +55,7 @@ export interface TagInputProps {
     style?: React.CSSProperties;
     style?: React.CSSProperties;
     suffix?: React.ReactNode;
     suffix?: React.ReactNode;
     validateStatus?: ValidateStatus;
     validateStatus?: ValidateStatus;
-    value?: string[];
+    value?: string[] | undefined;
     autoFocus?: boolean;
     autoFocus?: boolean;
 }
 }
 
 
@@ -140,12 +140,18 @@ class TagInput extends BaseComponent<TagInputProps, TagInputState> {
     }
     }
 
 
     static getDerivedStateFromProps(nextProps: TagInputProps, prevState: TagInputState) {
     static getDerivedStateFromProps(nextProps: TagInputProps, prevState: TagInputState) {
-        const {
-            value,
-            inputValue,
-        } = nextProps;
+        const { value, inputValue } = nextProps;
+        const { tagsArray: prevTagsArray } = prevState;
+        let tagsArray: string[];
+        if (isArray(value)) {
+            tagsArray = value;
+        } else if ('value' in nextProps && !value) {
+            tagsArray = [];
+        } else {
+            tagsArray = prevTagsArray;
+        }
         return {
         return {
-            tagsArray: isArray(value) ? value : prevState.tagsArray,
+            tagsArray,
             inputValue: isString(inputValue) ? inputValue : prevState.inputValue
             inputValue: isString(inputValue) ? inputValue : prevState.inputValue
         };
         };
     }
     }