React实现点击<p>标签跳转Catalog页仅展示is_hit=true商品
问题描述
我已经实现首页<p>标签跳转至"catalog"页面的导航功能,但不知道如何让点击该标签后,catalog页面仅展示is_hit === true的商品。目前catalog页面同时显示is_hit为true和false的商品,需要点击首页的<p>标签后,catalog页面移除所有is_hit不为true的商品,只保留符合条件的商品。尝试过一些方法但无效,相关代码如下:
首页部分代码
Хиты продаж {mainPageHits.map((item) => )} <p>Показать еще</p>
Catalog页面完整代码
import SideBarFilter from '../../components/UI/Catalog/SideBarFilter/SideBarFilter.jsx' import CardItem from '../../components/UI/Catalog/CardItem/CardItem.jsx' import {asyncGetProducts} from '../../redux/slices/getProductsSlice.jsx' import SideBar from '../../components/UI/Catalog/SideBar/SideBar.jsx' import Loading from '../../components/Base/Loading/Loading.jsx' import {useDispatch, useSelector} from 'react-redux' import React, {useState, useEffect} from 'react' import { useLocation } from 'react-router-dom'; import {useNavigate} from 'react-router-dom' import {links} from '../../links/links.jsx' import classes from './Catalog.module.sass' import axios from 'axios'; export default function Catalog() { const {products, loading} = useSelector(state => state.getProductsSlice) const navigate = useNavigate(); const dispatch = useDispatch(); const location = useLocation(); const [visibleItems, setVisibleItems] = useState(6); const [sortingType, setSortingType] = useState('priceDesc'); const [filteredProducts, setfilteredProducts] = useState([]); const handleShowMore = () => { setVisibleItems(prevVisibleItems => prevVisibleItems + visibleItems) } const applyFilters = (minPrice, maxPrice) => { const filtered = products.filter(item => item.price >= minPrice && item.price <= maxPrice) setfilteredProducts(filtered) } const sortProducts = (type, productsToSort) => { const sortedProducts = [...productsToSort]; switch (type) { case 'priceDesc': sortedProducts.sort((a, b) => b.price - a.price); break; case 'priceAsc': sortedProducts.sort((a, b) => a.price - b.price); break; case 'popularity': sortedProducts.sort((a, b) => b.popularity - a.popularity); break; case 'rating': sortedProducts.sort((a, b) => b.rating - a.rating); break; default: break; } return sortedProducts; }; useEffect(() => { axios.get('http://127.0.0.1:8000/api/v1/products/') .then(response => { console.log(response.data.results.filter(product => product.is_hit ===true)) }) .catch(error => { console.error('Error fetching data:', error); }); }, []); useEffect(() => { dispatch(asyncGetProducts()) }, [dispatch]) useEffect(() => { setfilteredProducts(products); }, [products]); if (loading) return <Loading/> return ( <div className={classes.catalog}> <div className={'container'}> <div className={classes.catalog_menuBar}> <div className={classes.catalog_menuBar_nav}> <ul> <li className={classes.catalog_menuBar_nav_br1} onClick={() => navigate(links.mainPage)}>Главное </li> <li> <svg width='23' height='24' viewBox='0 0 23 24' fill='none' xmlns='http://www.w3.org/2000/svg'> <path d='M13.8286 5.93018L19.6457 12.0002L13.8286 18.0702M3.354 12.0002H19.4828' stroke='#B0B0B0' strokeWidth='1.5' strokeMiterlimit='10' strokeLinecap='round' strokeLinejoin='round'/> </svg> </li> <li className={classes.catalog_menuBar_nav_br2}>Каталог</li> </ul> </div> </div> <div className={classes.catalog_inner}> <div className={classes.catalog_inner_left}> <div className={classes.catalog_inner_left_sideFilter}> <SideBar sortingType={sortingType} setSortingType={setSortingType} applyFilters={applyFilters}/> <SideBarFilter/> </div> </div> <div className={classes.catalog_inner_right}> <div className={classes.catalog_inner_right_itemsRow}> {sortProducts(sortingType, filteredProducts).slice(0, visibleItems).map((item) => <CardItem key={item.id} item={item} /> )} </div> {products && visibleItems < products.length && ( <button className={classes.catalog_inner_right_showBtn} onClick={handleShowMore}> Показать еще </button> )} </div> </div> </div> </div> ) }
解决方案
步骤1:修改首页跳转逻辑,添加查询参数
在首页的<p>标签跳转时,给catalog页面的URL加上标识筛选条件的查询参数,比如?filter=hit:
<p onClick={() => navigate(`${links.catalog}?filter=hit`)}>Показать еще</p>
如果是用<Link>组件,写法为:
<Link to={`${links.catalog}?filter=hit`}>Показать еще</Link>
步骤2:在Catalog组件中读取参数并过滤商品
替换原有的setfilteredProducts的useEffect,改为根据URL查询参数筛选商品:
// 移除原来的这个useEffect: // useEffect(() => { // setfilteredProducts(products); // }, [products]); // 新增处理查询参数的useEffect useEffect(() => { const searchParams = new URLSearchParams(location.search); const filter = searchParams.get('filter'); let result = [...products]; // 如果是hit筛选,只保留is_hit为true的商品 if (filter === 'hit') { result = result.filter(item => item.is_hit === true); } setfilteredProducts(result); }, [products, location.search]);
步骤3:调整"显示更多"按钮的判断逻辑
原来的按钮判断基于全部商品长度,现在要改为基于过滤后的商品长度:
{filteredProducts && visibleItems < filteredProducts.length && ( <button className={classes.catalog_inner_right_showBtn} onClick={handleShowMore}> Показать еще </button> )}
可选优化:后端API直接筛选(如果支持)
如果你的后端API支持根据is_hit字段筛选,可以在请求时直接带参数,减少前端处理的数据量。比如修改redux的asyncGetProducts请求:
useEffect(() => { const searchParams = new URLSearchParams(location.search); const filter = searchParams.get('filter'); // 传递筛选参数给redux请求 dispatch(asyncGetProducts(filter)); }, [dispatch, location.search]);
然后在asyncGetProducts的API请求中添加查询条件:
// 示例:redux切片中的请求逻辑 const fetchProducts = async (filter) => { let url = 'http://127.0.0.1:8000/api/v1/products/'; if (filter === 'hit') { url += '?is_hit=true'; } const response = await axios.get(url); return response.data; }
内容的提问来源于stack exchange,提问作者YOU KnoW
相关产品推荐
相关产品推荐

