
react 中因 `
在你提供的代码中,问题并非出在 useState 更新逻辑或 Filter 删除方式上,而是一个经典但容易被忽略的 dom 行为陷阱:
更严重的是,你的当前实现存在多个非 react 推荐的反模式:
- 使用全局变量 id 而非 React 状态,造成闭包和竞态风险;
- removeItem 中拼写错误:setMeal(NewList) → 应为 setMeal(newList)(大小写错误);
- 添加逻辑嵌套双层循环且依赖外部 id,可读性差、性能低(O(n×m));
- meal.concat(foods[i]) 是函数式写法,但未避免重复添加校验的竞态(因 meal 是旧快照)。
✅ 正确解法:将
以下是优化后的完整实现:
import React, { useState } from 'react'; import foods from 'json/foods'; const MealManager = () => { const [meal, setMeal] = useState([] as typeof foods); const [selectedFoodId, setSelectedFoodId] = useState(''); // ✅ 受控状态 const removeItem = (id: string) => { setMeal(prev => prev.filter(item => item.id !== id)); }; const handleAdd = () => { if (!selectedFoodId) return; const foodToAdd = foods.find(f => f.id === selectedFoodId); if (!foodToAdd) return; // ✅ 防重复:检查当前 meal 中是否已存在同 id 项(推荐用 id 判断,而非 name) if (meal.some(item => item.id === foodToAdd.id)) { alert(`"${foodToAdd.name}" is already in the list.`); return; } setMeal(prev => [...prev, foodToAdd]); // ✅ 函数式更新,确保基于最新状态 }; return ( {/* 渲染已选餐食 */} {meal.map((item) => ( {item.name}
Protein: {item.protein}
Fats: {item.fats}
Carbs: {item.carbs}
))}
{/* 添加区域:受控 select + 明确 Add 按钮 */}