Material-ui: [Autocomplete] Not refreshing options (used with async calls)

Created on 11 Mar 2020  路  6Comments  路  Source: mui-org/material-ui

  • [ x] The issue is present in the latest release.
  • [ x] I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 馃槸

Hello,
i'm implementing one autocomplete that call async function to retrive places in the world.
actually when i write a specific address ( ex. " viale dezza, melegnano" )
the api returns a single option ( https://nominatim.openstreetmap.org/search?format=json&addressdetails=1&polygon_svg=1&namedetails=1&q=viale%20dezza,%20melegnano )
and the state is updated, but the options inside the autocomplete select are not updated.

Expected Behavior 馃

when i write a specific address i would like to see the only one option that the api return

Steps to Reproduce 馃暪

----- > : https://codesandbox.io/s/recursing-night-m529o

Steps:

  1. click inside the autocomplete
  2. open console
  3. write "Viale dezza, melegnano"

Context 馃敠

autocomplete with react leflet etc.

Autocomplete docs good first issue

Most helpful comment

@diimii Thank you for the feedback. It's the second time I see somebody facing this problem. I think that we could improve the documentation on this matter. Basically, you need to disable the built-in filter: filterOptions={x => x}.

What do you think of the following diff? I wonder how we could better document this point 馃. Do you want to submit a pull request :).

diff --git a/docs/src/pages/components/autocomplete/GoogleMaps.tsx b/docs/src/pages/components/autocomplete/GoogleMaps.tsx
index 7937bc834..a90c467b1 100644
--- a/docs/src/pages/components/autocomplete/GoogleMaps.tsx
+++ b/docs/src/pages/components/autocomplete/GoogleMaps.tsx
@@ -43,6 +43,10 @@ interface PlaceType {
   };
 }

+const fetch = throttle((request: { input: string }, callback: (results?: PlaceType[]) => void) => {
+  (autocompleteService.current as any).getPlacePredictions(request, callback);
+}, 200);
+
 export default function GoogleMaps() {
   const classes = useStyles();
   const [inputValue, setInputValue] = React.useState('');
@@ -65,14 +69,6 @@ export default function GoogleMaps() {
     setInputValue(event.target.value);
   };

-  const fetch = React.useMemo(
-    () =>
-      throttle((request: { input: string }, callback: (results?: PlaceType[]) => void) => {
-        (autocompleteService.current as any).getPlacePredictions(request, callback);
-      }, 200),
-    [],
-  );
-
   React.useEffect(() => {
     let active = true;

@@ -97,7 +93,7 @@ export default function GoogleMaps() {
     return () => {
       active = false;
     };
-  }, [inputValue, fetch]);
+  }, [inputValue]);

   return (
     <Autocomplete
diff --git a/docs/src/pages/components/autocomplete/autocomplete.md b/docs/src/pages/components/autocomplete/autocomplete.md
index 3a1a2042c..3cfaf6e37 100644
--- a/docs/src/pages/components/autocomplete/autocomplete.md
+++ b/docs/src/pages/components/autocomplete/autocomplete.md
@@ -82,11 +82,21 @@ Head to the [Customized Autocomplete](#customized-autocomplete) section for a cu

 ## Asynchronous requests

+The component supports two different asynchronous use-cases.
+
+- [Load on open](#load-on-open): it waits for the component to be interacted with to load the options.
+- [Search as you type](#search-as-you-type): a new request is made for each keystroke.
+
+### Load on open
+
+It displays a progress state as long as the network request is pending.
+
 {{"demo": "pages/components/autocomplete/Asynchronous.js"}}

-### Google Maps place
+### Search as you type

 A customized UI for Google Maps Places Autocomplete.
+It's important to throttle the requests as well as disable the built-in filtering with `filterOptions={x => x}`.

 {{"demo": "pages/components/autocomplete/GoogleMaps.js"}}

All 6 comments

@diimii Thank you for the feedback. It's the second time I see somebody facing this problem. I think that we could improve the documentation on this matter. Basically, you need to disable the built-in filter: filterOptions={x => x}.

What do you think of the following diff? I wonder how we could better document this point 馃. Do you want to submit a pull request :).

diff --git a/docs/src/pages/components/autocomplete/GoogleMaps.tsx b/docs/src/pages/components/autocomplete/GoogleMaps.tsx
index 7937bc834..a90c467b1 100644
--- a/docs/src/pages/components/autocomplete/GoogleMaps.tsx
+++ b/docs/src/pages/components/autocomplete/GoogleMaps.tsx
@@ -43,6 +43,10 @@ interface PlaceType {
   };
 }

+const fetch = throttle((request: { input: string }, callback: (results?: PlaceType[]) => void) => {
+  (autocompleteService.current as any).getPlacePredictions(request, callback);
+}, 200);
+
 export default function GoogleMaps() {
   const classes = useStyles();
   const [inputValue, setInputValue] = React.useState('');
@@ -65,14 +69,6 @@ export default function GoogleMaps() {
     setInputValue(event.target.value);
   };

-  const fetch = React.useMemo(
-    () =>
-      throttle((request: { input: string }, callback: (results?: PlaceType[]) => void) => {
-        (autocompleteService.current as any).getPlacePredictions(request, callback);
-      }, 200),
-    [],
-  );
-
   React.useEffect(() => {
     let active = true;

@@ -97,7 +93,7 @@ export default function GoogleMaps() {
     return () => {
       active = false;
     };
-  }, [inputValue, fetch]);
+  }, [inputValue]);

   return (
     <Autocomplete
diff --git a/docs/src/pages/components/autocomplete/autocomplete.md b/docs/src/pages/components/autocomplete/autocomplete.md
index 3a1a2042c..3cfaf6e37 100644
--- a/docs/src/pages/components/autocomplete/autocomplete.md
+++ b/docs/src/pages/components/autocomplete/autocomplete.md
@@ -82,11 +82,21 @@ Head to the [Customized Autocomplete](#customized-autocomplete) section for a cu

 ## Asynchronous requests

+The component supports two different asynchronous use-cases.
+
+- [Load on open](#load-on-open): it waits for the component to be interacted with to load the options.
+- [Search as you type](#search-as-you-type): a new request is made for each keystroke.
+
+### Load on open
+
+It displays a progress state as long as the network request is pending.
+
 {{"demo": "pages/components/autocomplete/Asynchronous.js"}}

-### Google Maps place
+### Search as you type

 A customized UI for Google Maps Places Autocomplete.
+It's important to throttle the requests as well as disable the built-in filtering with `filterOptions={x => x}`.

 {{"demo": "pages/components/autocomplete/GoogleMaps.js"}}

@oliviertassinari Can I submit this pull request if @diimii doesn't want to?

@igorbrasileiro Definitely :)

this could be useful

                  `<Autocomplete
                            fullWidth
                            id="combo-box-demo"
                            options={top100Films}
                            getOptionLabel={(option) => option.title}
                            //setDataSend = my state ( const [ dataSend, setDataSend] = useState({}) )
                            onChange={(e,v) => setDataSend({...dataSend, exampleName : v})}
                            renderInput={(params) => 
                                <TextField 
                                    {...params}
                                    label="exampleName" 
                                    variant="outlined" 
                                    size="small" 
                                    required 
                                    name="exampleName"
                                    />
                            }
                        />`

I think we have something similar in this gist https://gist.github.com/sibelius/9b89371f2b846dcdb8bed3165ac372c3

it is an Autocomplete that integrates with Relay (graphql client to consume async data)

We have a connection of items (similar to array), we want to lazy load them when the user reaches the end of the dropdown

our problem is that the loadMoreItems of react-window-infinite-loader is only called once

we also need to refetch items when user search some of them

this component could be a lazy list of users, a lazy list of products

I still think this could use some clarification in the docs. I was losing my mind trying to figure out why on earth it wouldn't display my options once it got down to a seemingly low number of returned options.

What is the purpose of the option filter and why would it only be filtering sometimes? It seems that if my returned option list drops down to 3 or fewer options it stops displaying options unless I override this filter ...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chris-hinds picture chris-hinds  路  3Comments

rbozan picture rbozan  路  3Comments

ghost picture ghost  路  3Comments

iamzhouyi picture iamzhouyi  路  3Comments

pola88 picture pola88  路  3Comments