React状态数组过滤异常与搜索栏过滤实现求助
问题修复方案
一、解决「移除收藏时所有卡片被删除」的问题
问题根源:
- 参数传递不匹配:
Favorites组件调用handleUnlike时传入完整卡片对象,但App组件的handleUnlike函数预期接收卡片ID。 - 过滤条件逻辑错误:原
filter条件是保留ID等于传入值的项,导致反选所有其他项,最终清空数组。 - Key值不规范:
Favorites组件使用随机UUID作为key,React无法正确追踪列表项,引发异常渲染。
修改步骤:
- 修正
Favorites组件的参数传递:将onClick={() => handleUnlike(i)}改为onClick={() => handleUnlike(i.id)},传入卡片ID而非整个对象。 - 修正
App组件的过滤逻辑:将handleUnlike中的filter条件改为item.id !== id,保留不等于目标ID的项,实现移除指定卡片。 - 修复
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)); };
二、实现「搜索框过滤菜单卡片」功能
实现步骤:
- 在
App组件中添加搜索状态,存储输入框内容。 - 监听输入框的
onChange事件,更新搜索状态。 - 阻止表单默认提交行为,避免页面刷新。
- 根据搜索关键词过滤菜单数组,将过滤后的结果传给
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
相关产品推荐
相关产品推荐

