(
query: string | null,
opts: SearchOpts = {},
)
| 24 | |
| 25 | /** Pass a query to search the current server */ |
| 26 | export function useServerSearch( |
| 27 | query: string | null, |
| 28 | opts: SearchOpts = {}, |
| 29 | ): SearchResults { |
| 30 | const { debounce = 50, include = false, limit = 30 } = opts; |
| 31 | const [results, setResults] = useState([]); |
| 32 | const store = useStore(); |
| 33 | // Calculating the query takes a while, so we debounce it |
| 34 | const debouncedQuery = useDebounce(query, debounce); |
| 35 | |
| 36 | function createURLString(): string { |
| 37 | const url = new URL(store.getServerUrl()); |
| 38 | url.pathname = 'search'; |
| 39 | url.searchParams.set('q', debouncedQuery); |
| 40 | url.searchParams.set('include', include.toString()); |
| 41 | url.searchParams.set('limit', limit.toString()); |
| 42 | return url.toString(); |
| 43 | } |
| 44 | |
| 45 | const resource = useResource(createURLString()); |
| 46 | const [resultsIn] = useArray(resource, urls.properties.endpoint.results); |
| 47 | |
| 48 | // Only set new results if the resource is no longer loading, which improves UX |
| 49 | useEffect(() => { |
| 50 | if (!resource.loading && resultsIn) { |
| 51 | setResults(resultsIn); |
| 52 | } |
| 53 | }, [ |
| 54 | // Prevent re-rendering if the resultsIn is the same |
| 55 | resultsIn.toString(), |
| 56 | resource.loading, |
| 57 | ]); |
| 58 | |
| 59 | if (!query) { |
| 60 | return { |
| 61 | results: [], |
| 62 | loading: false, |
| 63 | error: undefined, |
| 64 | }; |
| 65 | } |
| 66 | |
| 67 | // Return the width so we can use it in our components |
| 68 | return { results, loading: resource.loading, error: resource.error }; |
| 69 | } |
no test coverage detected