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

React中useState实现鞋品数组品牌复选框筛选与渲染问题

解决React中品牌复选框筛选鞋品数组的逻辑问题

问题核心

当前实现的filterBrandHandler函数错误地将筛选后的数组追加到现有数组中,导致fetchedData变成二维数组,无法实现「勾选时添加对应品牌商品、取消勾选时移除对应品牌商品」的正确筛选逻辑。

问题分析

  1. 数据结构错误:setFetchData((current) => [...current, filterByBrand])会把筛选得到的数组作为单个元素推入原数组,最终fetchedData变成[原始数据, [筛选数据1], [筛选数据2]]的嵌套结构
  2. 逻辑方向错误:直接修改fetchedData会丢失原始数据的引用,取消勾选时无法基于原始数据重新计算筛选结果,只能在已被修改的数组上继续过滤,导致逻辑混乱

解决方案

正确的思路是维护选中品牌的集合,基于原始数据实时计算筛选结果,而不是直接修改存储数据的状态:

  1. 新增状态存储选中的品牌集合
  2. 复选框切换时,仅更新选中品牌集合
  3. 根据选中品牌集合,从原始result数组中计算出最终要渲染的筛选数据

修改后的完整代码

import type { NextPage } from 'next'
import { useState, useReducer } from "react";
import Pagination from '../../../components/Pagination';
import Modal from '../../../components/Modal';

type MenSneakersPageProps = {
  result: any[]
}

// 定义鞋品类型(替换any,提升类型安全性)
type Sneaker = {
  id: number;
  shortDescription: string;
  brand?: {
    id: number;
    name: string;
  };
  // 可根据实际结构补充其他字段
}
 
const MenSneakers: NextPage<MenSneakersPageProps> = ({ result }) => {
  // 维护选中品牌的集合,避免重复
  const [selectedBrands, setSelectedBrands] = useState<Set<string>>(new Set())
  const [modal, dispatch] = useReducer(reducer, initialState)

  // 优化品牌列表生成:用Set去重,更简洁高效
  const brandList = Array.from(
    new Set(result.map(item => item.brand?.name).filter(Boolean) as string[])
  ).sort()

  // 处理复选框切换:仅更新选中品牌集合
  const filterBrandHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
    const { value, checked } = event.target;
    setSelectedBrands(prev => {
      const newSet = new Set(prev);
      if (checked) {
        newSet.add(value);
      } else {
        newSet.delete(value);
      }
      return newSet;
    });
  }

  // 实时计算筛选后的结果
  const filteredData = selectedBrands.size === 0
    ? result // 没有选中任何品牌时,返回全部数据
    : result.filter(item => selectedBrands.has(item.brand?.name || ''))

  return (
    <div className='px-2'>
      <Modal onOpen={modal.secondModal} setPopUp={() => dispatch({ type:'closeModal2', value: false})}>
        <h2 className='text-2xl border-bottom border-b-4 border-black w-20 font-semibold pb-2'>Brands</h2>
        <hr/> 
        {brandList.map((item, index) => (        
          <ul className='mt-6' key={index}>
            <li className='my-6'>
              <input 
                className="mr-2" 
                type='checkbox' 
                id={`brand-${index}`} // 修复id重复问题
                value={item} 
                name='brand' 
                checked={selectedBrands.has(item)} // 设置正确的选中状态
                onChange={filterBrandHandler}
              />
              {item}
            </li>
          </ul>
        ))}
      </Modal>
      <Pagination data={filteredData} title="" pageLimit={2} dataLimit={30}/>
    </div>
  )
}

export default MenSneakers

关键优化点

  • 状态分离:用selectedBrands集合单独维护选中的品牌,避免直接修改数据数组
  • 基于原始数据计算:每次筛选都从原始result数组出发,确保取消勾选时能正确还原数据
  • 类型优化:新增Sneaker类型替换any,提升代码可维护性
  • 品牌列表生成优化:用Set去重,比循环判断更高效简洁
  • 修复复选框问题:设置正确的checked状态,避免复选框状态与实际选中集合不一致

内容的提问来源于stack exchange,提问作者schmulzcode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:50:41