本文详解如何在 react 中为含嵌套结构(如分组+选项列表)的数据实现精准、可重置的搜索功能,支持按子项字段模糊匹配并动态过滤层级,同时修复常见状态管理与事件传递错误。
在构建表单、配置面板或团队/角色选择器等场景中,常需对具有层级结构的数据(如 groups → options)进行搜索。例如,给定多个分组,每个分组包含若干带 label 的选项,目标是:输入关键词(如 "Team 1B"),仅返回匹配的分组及其内部精确匹配的选项,且清空输入时能完整恢复原始数据。
上述需求看似简单,但实际开发中易出现三大典型问题:
以下是完整、健壮的实现方案:
import React, { useState, useMemo } from 'react';
const groups = [
{
name: "Male 9 A",
options: [
{ label: "Team 1", selected: false },
{ label: "Team 2", selected: false },
{ label
: "Team 3", selected: false },
{ label: "Team 4", selected: false },
{ label: "Team 5", selected: false }
]
},
{
name: "Male 9 B",
options: [
{ label: "Team 1B", selected: false },
{ label: "Team 2B", selected: false },
{ label: "Team 3B", selected: false },
{ label: "Team 4B", selected: false },
{ label: "Team 5B", selected: false }
]
}
];
export default function App() {
const [searchTerm, setSearchTerm] = useState('');
// 使用 useMemo 缓存搜索结果,避免重复计算
const filteredGroups = useMemo(() => {
if (!searchTerm.trim()) return groups; // 空搜索 → 返回全部
const lowerTerm = searchTerm.toLowerCase();
return groups
.filter(group =>
// 匹配分组名 OR 分组内任意选项的 label
group.name.toLowerCase().includes(lowerTerm) ||
group.options.some(option => option.label.toLowerCase().includes(lowerTerm))
)
.map(group => ({
...group,
options: group.options.filter(option =>
option.label.toLowerCase().includes(lowerTerm)
)
}));
}, [searchTerm, groups]);
return (
setSearchTerm(e.target.value)}
/>
{filteredGroups.length === 0 ? (
No matches found.
) : (
filteredGroups.map((group, idx) => (
{group.name}
⚠️ 注意:原代码中 searchList(e) 未定义、searchFilter 被误设为初始 state、event 未透传等问题,均在此方案中彻底规避。始终让“原始数据不可变”、“搜索态可逆”,是构建可靠搜索功能的核心原则。