React事件分类筛选功能失效,请求技术排查
活动分类筛选器功能故障排查与修复方案
问题背景
需要实现活动分类筛选功能:选中对应分类后仅展示该分类下的活动,但当前功能无法正常工作,代码如下:
const EventSearchFilter: React.FC<IEventSearchFilterProps> = ({ eventData, }) => { const { data: categories } = useGetCategories(); const uniqueCategories = useMemo(() => { const categoriesId = [ ...new Set(eventData?.map((event) => event.categories).flat()), ]; const eventCategories = categoriesId?.map((id) => { return categories ?.filter((cat) => cat.id === id) .map((filtered) => ({ id, name: filtered.name, value: filtered.slug, })); }); return eventCategories?.flat().flat(); }, [eventData, categories]); const handleSelect = () => { }; const handleSearch = () => {}; return ( <StyledEventSearch> <Container> <Form> <Row> <Col xl={5} lg={5} md={6} sm={12}> <InputGroup> <AppInput onChange={handleSearch} placeholder={'Search for event'} icon={<AiOutlineSearch />} /> </InputGroup> </Col> <Col xl={2} lg={2} md={2} sm={4}> <Form.Group> <SelectInput placeholder="Select Industry" onChange={handleSelect} > {uniqueCategories} </SelectInput> </Form.Group> </Col> <Col xl={2} lg={2} md={2} sm={4}> <Form.Group> <SelectInput placeholder="Select Location" onChange={handleSelect} > {SELECT_INPUT_DATA} </SelectInput> </Form.Group> </Col> <Col xl={2} lg={2} md={2} sm={4}> <Form.Group> <SelectInput placeholder="Select Month" onChange={handleSelect}> {SELECT_INPUT_DATA} </SelectInput> </Form.Group> </Col> </Row> </Form> </Container> </StyledEventSearch> ); }; export default EventSearchFilter;
核心问题分析
- 无筛选状态管理:未使用React State存储用户选中的筛选条件(行业、地点、月份、搜索关键词),无法跟踪用户选择。
- 事件处理函数为空:
handleSelect和handleSearch未实现任何逻辑,既不更新状态,也不触发筛选动作。 - 缺少筛选逻辑:没有根据选中条件对
eventData进行过滤的代码,也未将过滤结果传递给父组件用于渲染。 - 筛选器事件区分缺失:三个
SelectInput共用同一个handleSelect,无法区分是哪个筛选器触发的选择,无法针对性更新状态。 - 选项格式可能不匹配:
uniqueCategories直接传入SelectInput,若组件要求选项必须包含label和value(而非name和value),会导致选项无法正常渲染。
修复方案与代码示例
关键修改点
- 添加状态存储筛选条件
- 实现区分筛选类型的事件处理函数
- 添加数据过滤逻辑
- 将过滤后的数据通过props传递给父组件(需在
IEventSearchFilterProps中添加onFilterChange回调) - 修正选项格式以匹配
SelectInput要求
修复后代码
import { useState, useMemo } from 'react'; // 定义筛选条件类型 type FilterParams = { industry: string | null; location: string | null; month: string | null; searchKeyword: string; }; const EventSearchFilter: React.FC<IEventSearchFilterProps & { onFilterChange: (filteredEvents: typeof eventData) => void; }> = ({ eventData, onFilterChange, }) => { const { data: categories } = useGetCategories(); // 初始化筛选状态 const [filters, setFilters] = useState<FilterParams>({ industry: null, location: null, month: null, searchKeyword: '', }); // 生成符合SelectInput要求的分类选项(假设组件需要label/value) const uniqueCategories = useMemo(() => { if (!eventData || !categories) return []; const categoriesId = [...new Set(eventData.map(event => event.categories).flat())]; return categoriesId.map(id => { const matchedCat = categories.find(cat => cat.id === id); return matchedCat ? { label: matchedCat.name, value: matchedCat.slug, } : null; }).filter(Boolean); }, [eventData, categories]); // 区分筛选类型的选择处理函数 const handleSelect = (type: keyof Omit<FilterParams, 'searchKeyword'>, value: string) => { setFilters(prev => ({ ...prev, [type]: value })); }; // 搜索输入处理 const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => { setFilters(prev => ({ ...prev, searchKeyword: e.target.value })); }; // 实时过滤数据 const filteredEvents = useMemo(() => { if (!eventData) return []; return eventData.filter(event => { // 行业筛选 if (filters.industry) { const eventCatSlugs = event.categories.map(catId => { const matchedCat = categories?.find(c => c.id === catId); return matchedCat?.slug; }).filter(Boolean); if (!eventCatSlugs.includes(filters.industry)) return false; } // 地点筛选(根据实际event结构调整字段) if (filters.location && event.location !== filters.location) return false; // 月份筛选(根据实际event日期格式调整) if (filters.month) { const eventMonth = new Date(event.date).toISOString().slice(0, 7); if (eventMonth !== filters.month) return false; } // 关键词搜索(根据实际event字段调整) if (filters.searchKeyword) { const keyword = filters.searchKeyword.toLowerCase(); return event.title.toLowerCase().includes(keyword) || event.description.toLowerCase().includes(keyword); } return true; }); }, [eventData, filters, categories]); // 把过滤结果传递给父组件 useMemo(() => { onFilterChange(filteredEvents); }, [filteredEvents, onFilterChange]); return ( <StyledEventSearch> <Container> <Form> <Row> <Col xl={5} lg={5} md={6} sm={12}> <InputGroup> <AppInput onChange={handleSearch} value={filters.searchKeyword} placeholder={'Search for event'} icon={<AiOutlineSearch />} /> </InputGroup> </Col> <Col xl={2} lg={2} md={2} sm={4}> <Form.Group> <SelectInput placeholder="Select Industry" onChange={(value) => handleSelect('industry', value)} value={filters.industry} > {uniqueCategories} </SelectInput> </Form.Group> </Col> <Col xl={2} lg={2} md={2} sm={4}> <Form.Group> <SelectInput placeholder="Select Location" onChange={(value) => handleSelect('location', value)} value={filters.location} > {SELECT_INPUT_DATA} </SelectInput> </Form.Group> </Col> <Col xl={2} lg={2} md={2} sm={4}> <Form.Group> <SelectInput placeholder="Select Month" onChange={(value) => handleSelect('month', value)} value={filters.month} > {SELECT_INPUT_DATA} </SelectInput> </Form.Group> </Col> </Row> </Form> </Container> </StyledEventSearch> ); }; export default EventSearchFilter;
额外说明
- 需根据实际的
eventData结构调整过滤逻辑中的字段(如location、date、title等) - 确认
SelectInput组件的选项格式要求,若原组件接受name/value,则无需修改uniqueCategories的字段名 - 父组件需传入
onFilterChange回调,接收过滤后的活动数据并用于渲染
内容的提问来源于stack exchange,提问作者mbc
相关产品推荐
相关产品推荐

