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

React状态数组过滤异常与搜索栏过滤实现求助

问题修复方案

一、解决「移除收藏时所有卡片被删除」的问题

问题根源:

  1. 参数传递不匹配:Favorites组件调用handleUnlike时传入完整卡片对象,但App组件的handleUnlike函数预期接收卡片ID。
  2. 过滤条件逻辑错误:原filter条件是保留ID等于传入值的项,导致反选所有其他项,最终清空数组。
  3. Key值不规范:Favorites组件使用随机UUID作为key,React无法正确追踪列表项,引发异常渲染。

修改步骤:

  1. 修正Favorites组件的参数传递:将onClick={() => handleUnlike(i)}改为onClick={() => handleUnlike(i.id)},传入卡片ID而非整个对象。
  2. 修正App组件的过滤逻辑:将handleUnlike中的filter条件改为item.id !== id,保留不等于目标ID的项,实现移除指定卡片。
  3. 修复Favorites组件的key值:将key={self.crypto.randomUUID()}改为key={i.id},使用稳定的卡片ID作为key。

修改后的代码片段:

Favorites组件:
export default function Favorites({ favorite, handleUnlike }) {
  return (
    <>
      <div className="holder">
        <h3>Favorites</h3>
        <div id="favorites">
          {favorite.map((i) => (
            <div
              className="col col-md mb-3 mb-sm-0"
              key={i.id}
            >
              <div className="card">
                <img src={i.image} alt="" className="card-img-top " />
                <div className="card-body">
                  <h5 className="card-title">{i.name}</h5>
                  <p className="card-text">{i.text}</p>
                  <a
                    onClick={() => handleUnlike(i.id)}
                    href="#"
                    className="btn btn-primary"
                  >
                    Remove
                  </a>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
}
App组件的handleUnlike函数:
const handleUnlike = (id) => {
  console.log("removed");
  setFavorite(favorite.filter((item) => item.id !== id));
};

二、实现「搜索框过滤菜单卡片」功能

实现步骤:

  1. 在App组件中添加搜索状态,存储输入框内容。
  2. 监听输入框的onChange事件,更新搜索状态。
  3. 阻止表单默认提交行为,避免页面刷新。
  4. 根据搜索关键词过滤菜单数组,将过滤后的结果传给Menu组件。

修改后的App组件完整代码:

import Favorites from "./Favorites";
import { Menu } from "./Menu";
import { useState } from "react";

import "./App.css";

function App() {
  const [favorite, setFavorite] = useState([]);
  const [array, setArray] = useState([
    {
      text: "Check 123",
      name: "Lahmacun",
      image: "src/lahmacun.jpeg",
      id: self.crypto.randomUUID(),
      liked: false,
    },
    {
      text: "Check 456",
      name: "Chicken",
      image: "src/chicken.webp",
      id: self.crypto.randomUUID(),
      liked: false,
    },
    {
      text: "Check 789",
      name: "Veggies",
      image: "src/vegan.jpeg",
      id: self.crypto.randomUUID(),
      liked: false,
    },
    {
      text: "Check 012",
      name: "Pho",
      image: "src/pho.jpeg",
      id: self.crypto.randomUUID(),
      liked: false,
    },
  ]);
  const [searchQuery, setSearchQuery] = useState("");

  const handleLike = (card) => {
    setFavorite((prev) => [...prev, card]);
  };

  const handleUnlike = (id) => {
    console.log("removed");
    setFavorite(favorite.filter((item) => item.id !== id));
  };

  const filteredMenu = array.filter(item => 
    item.name.toLowerCase().includes(searchQuery.toLowerCase()) || 
    item.text.toLowerCase().includes(searchQuery.toLowerCase())
  );

  const handleSubmit = (e) => {
    e.preventDefault();
  };

  return (
    <div id="app">
      <h1>Recipes To Try</h1>
      <form className="m-2" onSubmit={handleSubmit}>
        <div className="row">
          <div className="col-3 ">
            <label className="form-label pt-2" htmlFor="searchBar">
              Find A Recipe
            </label>
          </div>
          <div className="col-md-7 col-5">
            <input
              onChange={(e) => setSearchQuery(e.target.value)}
              type="text"
              className="form-control"
              id="searchBar"
              placeholder="Search"
              value={searchQuery}
            />
          </div>
          <div className="col-sm-1 col-2">
            <button type="submit" className="btn btn-primary" id="searchBtn">
              Search
            </button>
          </div>
        </div>
      </form>
      <Favorites favorite={favorite} handleUnlike={handleUnlike} />
      <Menu array={filteredMenu} handleLike={handleLike} />
    </div>
  );
}

export default App;

说明:

  • 搜索逻辑支持匹配菜品名称和描述文本,不区分大小写。
  • 将输入框改为受控组件,绑定value和onChange,确保状态与输入同步。
  • 修正了label的for属性(原代码中label与input的id重复,不符合规范)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:55:55