-
Notifications
You must be signed in to change notification settings - Fork 552
feat(autocomplete): support global onSelect and redirect to search page #6777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
70b00ac
4b0bcd9
cf22472
1441610
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,12 @@ import React, { | |
| useRef, | ||
| useState, | ||
| } from 'react'; | ||
| import { Index, useAutocomplete, useSearchBox } from 'react-instantsearch-core'; | ||
| import { | ||
| Index, | ||
| useAutocomplete, | ||
| useInstantSearch, | ||
| useSearchBox, | ||
| } from 'react-instantsearch-core'; | ||
|
|
||
| import { AutocompleteSearch } from '../components/AutocompleteSearch'; | ||
|
|
||
|
|
@@ -25,7 +30,7 @@ import type { | |
| Pragma, | ||
| AutocompleteClassNames, | ||
| } from 'instantsearch-ui-components'; | ||
| import type { BaseHit, Hit } from 'instantsearch.js'; | ||
| import type { BaseHit, Hit, IndexUiState } from 'instantsearch.js'; | ||
| import type { ComponentProps } from 'react'; | ||
|
|
||
| const Autocomplete = createAutocompleteComponent({ | ||
|
|
@@ -71,9 +76,11 @@ export type AutocompleteProps<TItem extends BaseHit> = ComponentProps<'div'> & { | |
| showSuggestions?: Partial< | ||
| Pick< | ||
| IndexConfig<{ query: string }>, | ||
| 'indexName' | 'itemComponent' | 'classNames' | ||
| 'indexName' | 'getURL' | 'itemComponent' | 'classNames' | ||
| > | ||
| >; | ||
| getSearchPageURL?: (nextUiState: IndexUiState) => string; | ||
| onSelect?: AutocompleteIndexConfig<TItem>['onSelect']; | ||
| classNames?: Partial<AutocompleteClassNames>; | ||
| }; | ||
|
|
||
|
|
@@ -83,13 +90,16 @@ type InnerAutocompleteProps<TItem extends BaseHit> = Omit< | |
| > & { | ||
| indicesConfig: Array<IndexConfig<TItem>>; | ||
| refineSearchBox: ReturnType<typeof useSearchBox>['refine']; | ||
| indexUiState: IndexUiState; | ||
| isSearchPage: boolean; | ||
| }; | ||
|
|
||
| export function EXPERIMENTAL_Autocomplete<TItem extends BaseHit = BaseHit>({ | ||
| indices = [], | ||
| showSuggestions, | ||
| ...props | ||
| }: AutocompleteProps<TItem>) { | ||
| const { indexUiState, indexRenderState } = useInstantSearch(); | ||
| const { refine } = useSearchBox( | ||
| {}, | ||
| { $$type: 'ais.autocomplete', $$widgetType: 'ais.autocomplete' } | ||
|
|
@@ -116,12 +126,17 @@ export function EXPERIMENTAL_Autocomplete<TItem extends BaseHit = BaseHit>({ | |
| ), | ||
| }, | ||
| getQuery: (item) => item.query, | ||
| onSelect: ({ getQuery, setQuery }) => { | ||
| setQuery(getQuery()); | ||
| }, | ||
| getURL: showSuggestions.getURL as unknown as IndexConfig<TItem>['getURL'], | ||
| }); | ||
| } | ||
|
|
||
| const isSearchPage = useMemo( | ||
| () => | ||
| typeof indexRenderState.hits !== 'undefined' || | ||
| typeof indexRenderState.infiniteHits !== 'undefined', | ||
| [indexRenderState] | ||
| ); | ||
|
Comment on lines
+133
to
+138
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it not possible to also get this info from the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now this is defined in the JS widget, and retrieving the index instance in React is not as easy ( Could be worth having it returned by the connector in a future update though. |
||
|
|
||
| return ( | ||
| <Fragment> | ||
| <Index EXPERIMENTAL_isolated> | ||
|
|
@@ -132,6 +147,8 @@ export function EXPERIMENTAL_Autocomplete<TItem extends BaseHit = BaseHit>({ | |
| {...props} | ||
| indicesConfig={indicesConfig} | ||
| refineSearchBox={refine} | ||
| indexUiState={indexUiState} | ||
| isSearchPage={isSearchPage} | ||
| /> | ||
| </Index> | ||
| </Fragment> | ||
|
|
@@ -141,17 +158,36 @@ export function EXPERIMENTAL_Autocomplete<TItem extends BaseHit = BaseHit>({ | |
| function InnerAutocomplete<TItem extends BaseHit = BaseHit>({ | ||
| indicesConfig, | ||
| refineSearchBox, | ||
| getSearchPageURL, | ||
| onSelect: userOnSelect, | ||
| indexUiState, | ||
| isSearchPage, | ||
| ...props | ||
| }: InnerAutocompleteProps<TItem>) { | ||
| const { indices, refine: refineAutocomplete } = useAutocomplete(); | ||
| const { getInputProps, getItemProps, getPanelProps, getRootProps } = | ||
| usePropGetters<TItem>({ | ||
| indices, | ||
| indicesConfig, | ||
| onRefine: (query: string) => { | ||
| onRefine: (query) => { | ||
| refineAutocomplete(query); | ||
| refineSearchBox(query); | ||
| }, | ||
| onSelect: | ||
| userOnSelect ?? | ||
| (({ query, setQuery, url }) => { | ||
| if (url) { | ||
| window.location.href = url; | ||
| return; | ||
| } | ||
|
|
||
| if (!isSearchPage && typeof getSearchPageURL !== 'undefined') { | ||
| window.location.href = getSearchPageURL({ ...indexUiState, query }); | ||
| return; | ||
| } | ||
|
|
||
| setQuery(query); | ||
| }), | ||
| }); | ||
|
|
||
| return ( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a possibility this can cause an indexing error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
targetIndex is at least the mainIndex (the parent of the isolated index of an autocomplete), so it should not cause an error. It just is typed as potentially undefined because the renderState needs to be declared before we have access to instantSearchInstance.