React中Fuse.js搜索为什么总是返回空数组?
在做一个带搜索功能的React组件时,用Fuse.js处理模糊搜索,但输入内容后结果一直是空数组…
代码是这样写的,初始化了Fuse实例,数据格式也检查过了没问题:
import Fuse from 'fuse.js';
function Search({ items }) {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
useEffect(() => {
const fuse = new Fuse(items, {
keys: ['name', 'description']
});
const res = fuse.search(query);
setResults(res);
}, [query]);
return (
<input onChange={e => setQuery(e.target.value)} />
{results.map(item => (
<div key={item.item.id}>{item.item.name}</div>
))}
);
}
输入测试数据时完全匹配的条目却搜不到,控制台也没报错,这是哪里出问题了?
---
### 第一步:检查
query的初始值在你的代码里,
query一开始是空字符串('')。当query为空时,fuse.search(query)会返回一个空数组,因为Fuse.js默认不会返回所有数据。你可以通过设置
Fuse的选项来改变这种行为,稍后再讲。---
### 第二步:理解
useEffect的触发时机你的
useEffect依赖了query,所以每次query变化都会重新创建一个Fuse实例。这其实是个性能问题,虽然不影响功能,但没必要每次都重新创建。我们可以优化一下,把Fuse实例提取到组件外或者用useRef缓存。---
### 第三步:正确处理搜索逻辑
你现在的逻辑是直接用
fuse.search(query)的结果更新results,但这里有一个小坑:当
query为空时,Fuse.js不会返回任何结果。如果你希望在这种情况下显示所有的items,需要手动处理这种情况。---
### 第四步:完整的解决方案代码
下面是修正后的代码,注释解释了每一步:
---
### 第五步:解释改动的地方
1. **Fuse实例缓存**
我用了
useRef来缓存Fuse实例,这样只有在组件首次加载时才会创建一次,避免不必要的性能开销。2. **处理空查询的情况**
当
query为空时,直接返回所有的items。这是为了让用户体验更好,而不是让用户看到空列表。3. **提取
item属性**fuse.search()返回的结果是一个对象数组,每个对象包含item和其他匹配信息。你需要提取出item部分才能正常渲染。4. **增加模糊匹配的阈值**
threshold参数控制模糊匹配的严格程度,默认值是0(完全匹配)。我把它改成了0.3,这样可以让搜索更宽松一些。---
### 第六步:测试和调试
记得用一些示例数据来测试这个组件,比如:
试着输入不同的关键词,看看结果是否符合预期。
---
如果你还有其他疑问,随时问!开发这些东西有时候确实有点绕,耐心调试就好~
useEffect里,你每次更新query都会重新创建一个Fuse实例。这样会导致性能问题,而且如果items没有正确更新,Fuse.js 搜索的结果肯定不对。直接用
useMemo把 Fuse 实例缓存起来,只在items变化时重新创建:这样写就对了。记住,不要在
useEffect里频繁创建大对象,用useMemo缓存一下能省不少事。