React中useState初始字符串值无法自动过滤产品求助
问题:页面加载时初始「All」过滤不生效,需手动点击才显示全部产品
我写了一段React代码用于点击过滤数组映射的产品内容,activeFilter初始化为'All',本该自动显示所有产品,但页面加载时没有生效,只有再次点击「All」按钮才会显示全部产品。相关代码如下:
import React, { useEffect, useState } from 'react' import {client} from '../lib/client' import { Product, FooterBanner, HeroBanner } from '../components' const Home = ({products, bannerData}) => { const [productItems, setProductItems] = useState([]) const [filterWork, setFilterWork] = useState([]); const [activeFilter, setActiveFilter] = useState('All'); useEffect(() => { setProductItems(products) }, []) const handleProductFilter = (item) => { setActiveFilter(item) setTimeout(() => { if (item == 'All'){ setFilterWork(productItems) }else{ setFilterWork(productItems.filter((productItem)=> productItem.tags.includes(item))) } }, 500) } return ( <> <HeroBanner heroBanner={bannerData.length && bannerData[0]} /> <div className='products-heading'> <h2>Best Selling Products</h2> <p>Smoke accessories of many variations</p> </div> <div className='product_filter'> {['Lighter', 'Pipe', 'Roller', 'Hookah', 'All'].map((item, index) => ( <div key={index} className={`product_filter-item app__flex p-text ${activeFilter === item ? 'item-active' : ''}`} onClick={() => handleProductFilter(item)} > {item} </div> ))} </div> <div className='products-container'> { filterWork.map((product) => <Product key={product._id} product={product} />) } </div> <FooterBanner footerBanner={bannerData && bannerData[0]} /> </> ) }; export const getServerSideProps = async () => { const query = '*[_type == "product"]' const products = await client.fetch(query) const bannerQuery = '*[_type == "banner"]' const bannerData = await client.fetch(bannerQuery) return { props: {products, bannerData} } } export default Home
页面加载时效果:初始「All」按钮处于激活状态,但无产品显示
原因分析
- filterWork初始为空数组:页面首次渲染时
filterWork是[],没有初始数据,导致产品列表无内容 - 未触发初始过滤逻辑:组件挂载时仅将
products赋值给productItems,但没有执行「All」对应的过滤操作 - setTimeout无必要且存在状态滞后:
handleProductFilter里的setTimeout不仅延迟了过滤,还依赖productItems的旧状态,初始挂载时可能还未完成赋值
解决方案
方案1:优化useEffect,自动触发初始过滤
修改useEffect,监听productItems和activeFilter的变化,自动更新过滤结果:
const Home = ({products, bannerData}) => { const [productItems, setProductItems] = useState([]) const [filterWork, setFilterWork] = useState([]); const [activeFilter, setActiveFilter] = useState('All'); // 初始化productItems,监听products变化 useEffect(() => { setProductItems(products); }, [products]) // 当productItems或activeFilter变化时,自动执行过滤 useEffect(() => { if (activeFilter === 'All') { setFilterWork(productItems); } else { setFilterWork(productItems.filter(product => product.tags.includes(activeFilter))); } }, [productItems, activeFilter]) const handleProductFilter = (item) => { setActiveFilter(item); // 移除不必要的setTimeout } // 其余return部分保持不变 }
方案2:简化逻辑,直接基于props计算过滤结果
省去productItems中间状态,直接使用传入的products计算过滤结果,减少状态层级:
const Home = ({products, bannerData}) => { const [activeFilter, setActiveFilter] = useState('All'); // 直接计算过滤结果,无需额外状态存储 const filterWork = activeFilter === 'All' ? products : products.filter(product => product.tags.includes(activeFilter)); const handleProductFilter = (item) => { setActiveFilter(item); } // 其余return部分保持不变 }
内容的提问来源于stack exchange,提问作者Chidimma Nworah
相关产品推荐
相关产品推荐

