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

如何在多层级对象数组中使用filter()方法?

解决多层级对象数组的filter筛选问题

首先,你的代码存在两个核心问题:useEffect的依赖数组未包含bodypart状态,导致选择变化时不会重新执行筛选逻辑;其次,筛选逻辑没有正确处理嵌套的对象结构。以下是修正后的完整方案:

修正后的React组件代码

import React, { useState, useEffect } from "react";

const tattoos = [
  {
    head: [
      { name: "1 - Crâne de pirate (H/F)", gender: "HF", price: "450" },
      { name: "2 - Surf LS (H/F)", gender: "HF", price: "250" },
    ],
    torso: [
      { name: "1 - Crâne de pirate (H/F)", gender: "HF", price: "450" },
      { name: "2 - Surf LS (H/F)", gender: "HF", price: "250" },
    ],
  },
];

export default function Searchbar() {
  const [filtered, setFiltered] = useState([]);
  const [bodypart, setBodypart] = useState("all");

  function handleChange(e) {
    setBodypart(e.target.value);
  }

  useEffect(() => {
    if (bodypart === "all") {
      // 收集所有部位的纹身,扁平化处理
      const allTattoos = tattoos.flatMap(collection => 
        Object.values(collection).flat()
      );
      setFiltered(allTattoos);
      return;
    }

    // 筛选指定部位的纹身,跨多个collection合并结果
    const filteredTattoos = tattoos.flatMap(collection => 
      collection[bodypart] || []
    );
    setFiltered(filteredTattoos);
  }, [bodypart]); // 依赖bodypart,状态变化时重新执行

  return (
    <div>
      <div>
        <label>身体部位:</label>
        <select onChange={handleChange} value={bodypart}>
          <option value="all">全部</option>
          <option value="head">头部</option>
          <option value="torso">躯干</option>
        </select>
      </div>
      {/* 示例:渲染筛选后的纹身列表 */}
      <div className="tattoos-list">
        {filtered.map((tattoo, index) => (
          <div key={index}>
            <h3>{tattoo.name}</h3>
            <p>价格: ${tattoo.price}</p>
            <p>适用性别: {tattoo.gender}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

关键修正点说明

  1. 修复useEffect依赖:将bodypart加入依赖数组,确保下拉选择变化时自动重新执行筛选逻辑。
  2. 正确处理嵌套结构:
    • 当选择"all"时,用flatMap和Object.values(collection).flat()遍历所有部位的纹身数组并扁平化,得到所有纹身的一维数组。
    • 选择特定部位时,通过collection[bodypart]直接获取对应部位的纹身数组,再用flatMap合并多个collection的结果。
  3. 优化select组件:添加value={bodypart}确保下拉框显示与当前状态一致。

你之前尝试失败的原因

  • tattoos.filter(e => e === bodypart):e是包含head/torso的对象,和字符串比较永远为false,返回空数组。
  • e.includes(bodypart):对象没有includes方法,直接报错。
  • e.some(bodypart):some是数组方法,对象调用会报错。
  • Objects.keys(e).includes(bodypart):返回的是包含该部位的collection对象数组,而非具体的纹身列表,不符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 05:07:47