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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:20:34