You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:35:37