Debounce issue on Autocomplete + Instantsearch

Hi all!
I’m having an issue to make debounce work when using Autocomplete with Instantsearch using this guide and this one for debounce

Everything works properly, but all the queries are sent to Algolia immediately without waiting for debounce. My goal is to limit the number of queries by using debounce. The problem appeared when adding instant search, it worked perfectly when autocomplete was standalone.

I think the problem comes from:

onStateChange({ prevState, state }) {
    if (prevState.query !== state.query) {
      setInstantSearchUiState({ query: state.query })
    }
  },

but I couldn’t figure out what’s the issue.

Anyone has an idea? Thanks in advance!

Full autocomplete function

autocomplete({
  container: '#autocomplete',
  placeholder: 'Search for simulations',
  detachedMediaQuery: 'none',
    // You want recent searches to appear with an empty query.
  openOnFocus: true,
  // Add the recent searches plugin.
  plugins: [recentSearchesPlugin],
  onStateChange({ prevState, state }) {
    if (prevState.query !== state.query) {
      debouncedSetInstantSearchUiState({ query: state.query })
    }
  },
  initialState: {
    query: searchPageState.query || '',
  },
  onSubmit({ state }) {
    setInstantSearchUiState({ query: state.query })
  },
  onReset() {
    setInstantSearchUiState({ query: '' })
  },
  onStateChange({ prevState, state }) {
    if (prevState.query !== state.query) {
      setInstantSearchUiState({ query: state.query })
    }
  },
  getSources({ query }) {
     return debounced([
      {
        sourceId: 'products',
        onSelect({ item }) {
          window.location.assign(`/simulations/${item.Slug}`)
        },
        getItemUrl({ item }) {
          return `/simulations/${item.Slug}`
        },
        getItems() {
          return getAlgoliaResults({
            searchClient,
            queries: [
              {
                indexName: INSTANT_SEARCH_INDEX_NAME,
                query,
                params: {
                  hitsPerPage: 5,
                  attributesToSnippet: ['Name:10', 'Short_description:35'],
                  snippetEllipsisText: '…',
                },
              },
            ],
          });
        },
        templates: {
        noResults() {
            return 'No results.';
          },
          item({ item, components, html }) {
            return html`<div class="aa-ItemWrapper">
              <div class="aa-ItemContent">
                <div class="aa-ItemContentBody">
                  <div class="aa-ItemContentTitle">
                    ${components.Highlight({
                      hit: item,
                      attribute: 'Name',
                    })}
                  </div>
                  <div class="aa-ItemContentDescription">
                    ${components.Snippet({
                      hit: item,
                      attribute: 'Short_description',
                    })}
                  </div>
                </div>
              </div>
            </div>`;
          },
        },
      },
    ]);
  },
});

good afternoon,

i am having the same problem using the debounce functionality specified here: Integrate Autocomplete with React InstantSearch Hooks | Autocomplete | Algolia . I am using a remix app with a component library inside a monorepo (lerna & nx), any thoughts would be appreciated

Hi @yan

Sorry for the late reply. When you added the new code using debouncedSetInstantSearchUiState in your onStateChange, you forgot to remove the previous onStateChange code below it. Your autocomplete should look like this:

autocomplete({
  container: '#autocomplete',
  placeholder: 'Search for simulations',
  detachedMediaQuery: 'none',
    // You want recent searches to appear with an empty query.
  openOnFocus: true,
  // Add the recent searches plugin.
  plugins: [recentSearchesPlugin],
  onStateChange({ prevState, state }) {
    if (prevState.query !== state.query) {
      debouncedSetInstantSearchUiState({ query: state.query })
    }
  },
  initialState: {
    query: searchPageState.query || '',
  },
  onSubmit({ state }) {
    setInstantSearchUiState({ query: state.query })
  },
  onReset() {
    setInstantSearchUiState({ query: '' })
  },
  getSources({ query }) {
     return debounced([
      {
        sourceId: 'products',
        onSelect({ item }) {
          window.location.assign(`/simulations/${item.Slug}`)
        },
        getItemUrl({ item }) {
          return `/simulations/${item.Slug}`
        },
        getItems() {
          return getAlgoliaResults({
            searchClient,
            queries: [
              {
                indexName: INSTANT_SEARCH_INDEX_NAME,
                query,
                params: {
                  hitsPerPage: 5,
                  attributesToSnippet: ['Name:10', 'Short_description:35'],
                  snippetEllipsisText: '…',
                },
              },
            ],
          });
        },
        templates: {
        noResults() {
            return 'No results.';
          },
          item({ item, components, html }) {
            return html`<div class="aa-ItemWrapper">
              <div class="aa-ItemContent">
                <div class="aa-ItemContentBody">
                  <div class="aa-ItemContentTitle">
                    ${components.Highlight({
                      hit: item,
                      attribute: 'Name',
                    })}
                  </div>
                  <div class="aa-ItemContentDescription">
                    ${components.Snippet({
                      hit: item,
                      attribute: 'Short_description',
                    })}
                  </div>
                </div>
              </div>
            </div>`;
          },
        },
      },
    ]);
  },
});

This assumes you are properly defining const debouncedSetInstantSearchUiState using the appropriate debounce logic above this code.

I was able to get all of this working with the sample code from Integrate Autocomplete with InstantSearch.js | Autocomplete | Algolia

1 Like

Thank you @chuck.meyer , that solved it! As often, the problem was between the chair and the screen :slight_smile:

1 Like

Glad to hear, @yan! Feel free to share your final page when you’re done. I love seeing sites that follow the Autocomplete + InstantSearch pattern.

@akarim – let me know if this helped you as well. If not, maybe start a new thread with your code?

If I can pick your brain for a second small question:

I want that if I click the Autocomplete value, the autocomplete input gets filled with the item name.

I have something like this in my autocomplete function:

onSelect({ item }) {
         setInstantSearchUiState({ query: item.name });
        },

It updates the Instantsearch widget correct, but the autocomplete input doesn’t get filled with the value. Any idea? :slight_smile:

Hey, yeah that will just inject into the underlying InstantSearch, not the autocomplete object. You should be able to do that using setQuery. Give it a try.