React Hooks+Redux实现子组件复选框筛选数据传值给父产品列表
实现方案(Props回调方式,无需改动Redux逻辑,适配当前场景)
第一步:修改父组件 ProductList.jsx
- 新增状态存储筛选后的产品列表,定义筛选回调函数传递给子组件
- 渲染产品时优先使用筛选后的列表,无筛选条件时默认展示全量产品
修改后完整代码:
const ProductList = () => { const dispatch = useDispatch(); // 新增状态:存储筛选后的产品列表 const [filteredProducts, setFilteredProducts] = useState([]); const getalldatafromserver = useSelector((state)=>{ return state.FetchALLProducts; }) useEffect(() => { dispatch(allActions.fetchallproducts()); }, []) // 新增:产品数据加载完成后默认初始化筛选列表为全量数据 useEffect(() => { setFilteredProducts(getalldatafromserver.products) }, [getalldatafromserver.products]) // 新增:接收子组件传递的筛选结果的回调函数 const handleFilterChange = (filteredList) => { setFilteredProducts(filteredList) } return ( <React.Fragment> <div className="container"> <div className="row"> <div className="col-md-2"> {/* 给子组件传递回调函数 */} <SideNav onFilter={handleFilterChange} /> </div> <div className="col-md-10"> <section className="mt-3"> <div className="container"> <div className="row"> <div className="col"> <p className="h3 text-success">Product List</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ex impedit, incidunt ipsum nulla sapiente sint suscipit? A animi, error et fuga ipsum minus, nam officia praesentium quisquam, recusandae soluta voluptate?</p> </div> </div> </div> </section> <section> <div className="container"> <div className="row"> { filteredProducts.length > 0 && filteredProducts.map(product => { return ( <div className="col-md-3" key={product.id}> <div className="card"> <div className="card-header text-center bg-white"> <img src={product.image} alt="" width="150" height="150"/> </div> <div className="card-body rgba-light-green-light"> <ul className="list-group"> <li className="list-group-item"> NAME : {product.name} </li> <li className="list-group-item"> PRICE : {product.price} </li> <li className="list-group-item"> QTY : {product.qty} Kgs </li> </ul> </div> </div> </div> ) }) } </div> <div className="row"> <div className="col"> { filteredProducts.length === 0 && <p className="font-weight-bold text-success text-center fw-bold">NO Records Found in Database</p> } </div> </div> </div> </section> </div> </div> </div> </React.Fragment> ) }
第二步:修改子组件 SideNav.jsx
- 接收父组件传递的
onFilter回调 - 修正筛选逻辑:每次复选框变化(包括全选)时,先获取所有已勾选的产品名称,再筛选出匹配的全部产品,调用回调传递给父组件
修改后完整代码:
const SideNav = ({onFilter}) => { //Get data from Store const getDataFromStore = useSelector((state)=>{ return state.FetchALLProducts; }) const [sidebar, setsidebar] = useState(false); const [checkBoxes, setcheckBoxes] = useState([ {name:"Orange",isChecked:false}, {name:"Carrot",isChecked:false}, {name:"Apple",isChecked:false}, {name:"Potato",isChecked:false}, {name:"Avacados",isChecked:false} ]) const showSidebar =() =>{ setsidebar(true); } // 新增:通用筛选方法,复选框变化/全选时都调用 const filterProducts = (checkboxList) => { const allProducts = [...getDataFromStore.products]; // 获取所有已勾选的产品名称 const checkedNames = checkboxList.filter(item => item.isChecked).map(item => item.name); let filteredList = allProducts; // 有勾选条件时筛选,无勾选时返回全量 if(checkedNames.length > 0){ filteredList = allProducts.filter(product => checkedNames.includes(product.name)) } // 调用父组件回调传递筛选结果 onFilter(filteredList) } const handleCheckChnage =(e) =>{ const allcheckboxes = [...checkBoxes]; allcheckboxes.forEach((cbox)=>{ if(cbox.name === e.target.value){ cbox.isChecked = !cbox.isChecked } }) setcheckBoxes(allcheckboxes); // 调用筛选方法 filterProducts(allcheckboxes) } const selectAll =(e) =>{ const newcheckboxes = [...checkBoxes]; newcheckboxes.forEach((allbox)=>{ allbox.isChecked = e.target.checked; }) setcheckBoxes(newcheckboxes); // 调用筛选方法 filterProducts(newcheckboxes) } return ( <React.Fragment> <i className="fas fa-align-justify yes" onClick={showSidebar} ></i> { sidebar && <div className="form-group mt-3"> <label className="mb-2 fw-bold">Choose Health</label> <br/> <input className="form-check-input" type="checkbox" name="all" onChange={(e)=>{selectAll(e)}} /> <span style={{marginLeft:'5px',fontWeight:"bold"}}>All Skils</span> { checkBoxes.map((cb)=> <div className="form-check" key={cb.name}> <label className="form-check-label" >{cb.name}</label> <input className="form-check-input" type="checkbox" name="checking" value={cb.name} checked={cb.isChecked} onChange={(e)=>{handleCheckChnage(e)}} /> </div> ) } </div> } </React.Fragment> ) } export default SideNav;
内容的提问来源于stack exchange,提问作者sundeep
相关产品推荐
相关产品推荐

