React中Filter组件与Card组件联动筛选异常问题排查
Filter组件与Card联动二次筛选失效问题解决
问题描述
实现Filter组件与Card组件联动:用户选择筛选条件后展示符合条件的Card。首次点击筛选按钮能正确显示对应Card,但再次点击其他筛选按钮时所有Card消失。
问题原因
父组件中,profissionais状态既存储了从API获取的原始全量数据,又被用来存储筛选后的结果。每次执行itensFiltrado函数时,会把profissionais替换成当前筛选的子集,导致后续筛选只能在这个子集里进行,无法找到其他分类的数据,最终所有Card消失。
解决方案
拆分状态:用一个状态存储原始全量数据,另一个状态存储筛选后的结果,始终基于原始数据进行筛选操作。
修改后的父组件代码
import React, { useEffect, useState } from "react"; import "./popupOrcamentoSimultaneo.css"; import Filtro from "./Filtro"; import Card from "./Card"; import api from "../../../../api"; function PopupOrcamentoSimultaneo({ setOpenPopup, checkedState }) { // 存储原始全量数据,永远不修改 const [originalProfissionais, setOriginalProfissionais] = useState([]); // 存储筛选后的结果,用于渲染卡片 const [profissionais, setProfissionais] = useState([]); const [filtros, setFiltros] = useState([]); const [value, setValue] = useState( "Olá! Vamos nos casar e gostariamos de mais informações sobre seu serviço." ); useEffect(() => { api.get("profissionais/listarTodos/").then(({ data }) => { setOriginalProfissionais(data); setProfissionais(data); // 初始显示全部数据 const setOfFilters = new Set( data.map((profissional) => profissional.segmento) ); setFiltros([...setOfFilters]); }); }, []); const itensFiltrado = (segmentoEmpresa) => { // 基于原始全量数据进行筛选 const novosProfissionais = originalProfissionais.filter( (profissional) => profissional.segmento === segmentoEmpresa ); setProfissionais(novosProfissionais); }; // 优化卡片渲染:用map替代for循环更简洁 const listaCardsProfissionais = profissionais.map(profissional => ( <Card key={profissional.idProfissional} dadosProfissionais={profissional} /> )); const changeValue = (e) => { setValue(e.target.value); }; return ( <div className="popup"> <div className="popup__container"> <div className="close-container" onClick={() => setOpenPopup(false)}> <i className="fa-solid fa-xmark"></i> </div> <h2 className="popup__titulo"> Solicite orçamento à outros profissionais simultaneamente! </h2> <Filtro filtros={filtros} itensFiltrado={itensFiltrado} /> <h3 className="popup__subtitulo"> Profissionais recomendados para você. </h3> <div className="cards__profissionais">{listaCardsProfissionais}</div> <div className="input-box"> <label for="input" className="input-label"> Escreva sua mensagem </label> <div> <input type="text" id="input" className="input-text" placeholder="Olá! Vamos nos casar e gostariamos de mais informações sobre seu serviço." value={value} onChange={changeValue} /> <i className="fa-solid fa-pencil"></i> </div> </div> </div> </div> ); } export default PopupOrcamentoSimultaneo;
关键修改点
- 新增
originalProfissionais状态,专门存储从API获取的全量数据,后续不会修改这个状态。 profissionais状态改为存储筛选后的结果,初始值设置为全量数据,保证页面加载时显示所有Card。- 修改
itensFiltrado函数,基于originalProfissionais进行筛选,确保每次筛选都是从完整的数据源中查找。 - 优化卡片渲染逻辑,用
Array.map()替代for循环,代码更简洁且符合React最佳实践。
额外优化建议
- 可以添加一个「显示全部」的筛选选项,让用户可以快速回到全量数据视图。
- Filter组件中的单选按钮可以和筛选状态绑定,让用户直观看到当前选中的筛选条件。
内容的提问来源于stack exchange,提问作者Caio Lagreca
相关产品推荐
相关产品推荐

