Repository: mui/material-ui (TypeScript)
Date: 2019-12-27 05:05:33+00:00
Task type: Bug Fix

Issue:
[Autocomplete] Zero (0) integer key display throws
An **Autocomplete** component with a list of integer values with zero, e.g. `[0, 10, 20]` stops displaying proper popup after selecting "0" and displays "No options" instead if `getOptionLabel` is used, e.g:

```js
getOptionLabel={option => option === 0 ? "Any" : option.toString()}
```

Please check out this example:
https://codesandbox.io/embed/autocomplete-any-2vfmv

Steps:

1) Click in the **LEFT** control
2) Select "20" from the drop-down
3) Click outside of the control
4) Click in the control again and note that _a)_ popup is opened and _b)_ "20" is selected there
5) Now select "Any" from the list
6) Click outside of the control
7) Click back in the control: no drop-down is displayed, we see only "No options"

Now do the same with the **RIGHT** control, where the value of ten (10) and not zero (0) is rewritten to "Any". See that this behavior is gone and you can now select any value and get drop-down properly displayed.


Issue discussion:
@OnkelTem Thank you for the bug report. It's an issue with the value `0`.

What do you think of this diff? Do you want to submit a pull request? :)

```diff
diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
index feb69e2f2..e3634d0ce 100644
--- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
+++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
@@ -208,7 +208,7 @@ export default function useAutocomplete(props) {
   const open = isOpenControlled ? openProp : openState;

   const inputValueFilter =
-    !multiple && value && inputValue === getOptionLabel(value) ? '' : inputValue;
+    !multiple && value != null && inputValue === getOptionLabel(value) ? '' : inputValue;

   let popupOpen = open;
```
@oliviertassinari Working on this.
@xZliman Should we add a unit test? 🤔
@oliviertassinari Yes we can add a unit test to cover that case
OK cool, I believe we don't test this feature at all, it would be an opportunity to cover it, with this edge case. 
@xZliman Did you make progress? :)
Hi @oliviertassinari, I didn't find the time to write the tests. 

Solution patch:
diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
--- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
+++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
@@ -232,8 +232,8 @@ export default function useAutocomplete(props) {
   const [openState, setOpenState] = React.useState(false);
   const open = isOpenControlled ? openProp : openState;
 
-  const inputValueFilter =
-    !multiple && value && inputValue === getOptionLabel(value) ? '' : inputValue;
+  const inputValueIsSelectedValue =
+    !multiple && value != null && inputValue === getOptionLabel(value);
 
   let popupOpen = open;
 
@@ -250,7 +250,9 @@ export default function useAutocomplete(props) {
           }
           return true;
         }),
-        { inputValue: inputValueFilter },
+        // we use the empty string to manipulate `filterOptions` to not filter any options
+        // i.e. the filter predicate always returns true
+        { inputValue: inputValueIsSelectedValue ? '' : inputValue },
       )
     : [];
 
@@ -585,7 +587,7 @@ export default function useAutocomplete(props) {
               inputRef.current.value.length,
             );
           }
-        } else if (freeSolo && inputValueFilter !== '') {
+        } else if (freeSolo && inputValue !== '' && inputValueIsSelectedValue === false) {
           selectNewValue(event, inputValue);
         }
         break;


Test patch:
diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
--- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
+++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
@@ -889,4 +889,34 @@ describe('<Autocomplete />', () => {
       expect(textbox).to.not.have.focus;
     });
   });
+
+  describe('prop: getOptionLabel', () => {
+    it('is considered for falsy values when filtering the the list of options', () => {
+      const { getAllByRole } = render(
+        <Autocomplete
+          options={[0, 10, 20]}
+          getOptionLabel={option => (option === 0 ? 'Any' : option.toString())}
+          renderInput={params => <TextField {...params} autoFocus />}
+          value={0}
+        />,
+      );
+
+      const options = getAllByRole('option');
+      expect(options).to.have.length(3);
+    });
+
+    it('is not considered for nullish values when filtering the list of options', () => {
+      const { getAllByRole } = render(
+        <Autocomplete
+          options={[null, 10, 20]}
+          getOptionLabel={option => (option === null ? 'Any' : option.toString())}
+          renderInput={params => <TextField {...params} autoFocus />}
+          value={null}
+        />,
+      );
+
+      const options = getAllByRole('option');
+      expect(options).to.have.length(3);
+    });
+  });
 });