Search
import {useState} from 'react' import {useMemoObservable} from 'react-rx-old' import {Observable} from 'rxjs' import {of, timer} from 'rxjs' import { debounceTime, distinctUntilChanged, filter, map, switchMap, } from 'rxjs/operators' interface SearchResult { keyword: string hits: Hit[] } interface Hit { title: string } const range = (len: number) => { const res = [] for (let i = 0; i <= len; i++) { res.push(null) } return res } // A search function that takes longer time to complete for shorter keywords // e.g. a keyword of one character takes 9 seconds while a keyword of 9 characters takes 1 second const search = ( keyword: string, ): Observable<SearchResult> => { const delay = Math.max( 1, Math.round(10 - keyword.length), ) return timer(delay * 200).pipe( map(() => range(delay).map((_, i) => ({ title: `Hit #${i}`, })), ), map((hits) => ({ keyword, hits, })), ) } function SearchExample() { const [keyword, setKeyword] = useState('') return ( <> <input type="search" style={{ width: '100%', }} value={keyword} placeholder="Type a keyword to search" onChange={(event) => setKeyword(event.target.value) } /> <div> The more characters you type, the faster the results will appear </div> {useMemoObservable( () => of(keyword).pipe( debounceTime(200), distinctUntilChanged(), filter((v) => v !== ''), switchMap((kw: string) => search(kw)), map((result: SearchResult) => ( <> <h1> Searched for {result.keyword} </h1> <div> Got {result.hits.length} hits </div> <ul> {result.hits.map((hit, i) => ( <li key={i}>{hit.title}</li> ))} </ul> </> )), ), [keyword], )} </> ) } export default SearchExample