Skip to content

Instantly share code, notes, and snippets.

@f-ricci
Created June 11, 2020 07:46
Show Gist options
  • Save f-ricci/156d9fe3913f332907173a646318f20e to your computer and use it in GitHub Desktop.
Save f-ricci/156d9fe3913f332907173a646318f20e to your computer and use it in GitHub Desktop.
Hook wrapper for fuse.js
import { useState, useEffect } from 'react';
import Fuse from 'fuse.js';
const DEFAULT_OPTIONS: IUseMemorySearch<any> = {
minSearchLength: 3,
transformCallback: results => results.map(({ item }) => item),
searchOptions: {
useExtendedSearch: true,
threshold: 0.3,
keys: ['title'],
}
};
export function useMemorySearch<R>(
pattern: string | Fuse.Expression,
data: R[],
options?: IUseMemorySearch<R>
): ISearchResult<R> {
const [stateOptions, setStateOptions] = useState({ ...DEFAULT_OPTIONS, ...options });
const [statePattern, setStatePattern] = useState(pattern);
const [stateData, setStateData] = useState<R[]>(data);
const [searchResult, setSearchResult] = useState<R[]>(data);
const [isDirty, setIsDirty] = useState(false);
useEffect(() => {
if (!isDirty) {
setSearchResult(stateData);
return;
}
switch (typeof statePattern) {
case 'string':
if (statePattern.length >= stateOptions.minSearchLength) {
const fuse = new Fuse(stateData, stateOptions.searchOptions);
const results = stateOptions.transformCallback(fuse.search(statePattern));
setSearchResult(results);
} else if (isDirty) {
setSearchResult([]);
}
break;
default:
const fuse = new Fuse(stateData, stateOptions.searchOptions);
const results = stateOptions.transformCallback(fuse.search(statePattern));
setSearchResult(results);
break;
}
}, [statePattern, stateData, stateOptions, isDirty]);
useEffect(() => setStateData(data), [data]);
useEffect(() => setStatePattern(pattern), [pattern]);
useEffect(() => setStateOptions(stateOptions), [stateOptions]);
useEffect(() => {
switch (typeof statePattern) {
case 'string':
setIsDirty(statePattern.length > 0);
break;
default:
setIsDirty(true);
break;
}
}, [statePattern]);
return { searchResult };
}
interface IUseMemorySearch<R> {
minSearchLength: number
searchOptions: Fuse.IFuseOptions<R>
transformCallback: (results: Fuse.FuseResult<R>[]) => any
}
interface ISearchResult<R> {
searchResult: R[]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment