javascript - 当对象位于对象数组中时如何从状态中删除对象
问题描述
我正在尝试通过 id 从对象中的数组中删除一个对象。我不知道该怎么做……我看过其他几篇帖子,但我觉得设置有点不同,所以我还是不明白。
deleteMeals
即使我获取了正确的用餐 ID,也不会删除正确的对象。“星期一”也作为占位符/试图弄清楚事情。
我之前的store
设置有所不同,每个餐点对象都有自己的day
键,并且我可以删除 - 除了第一个对象(id:1)直到它是最后一个对象才会删除。我最终重构了商店,以便每个用餐对象都在一个由实际 Day 分隔的数组中。
所以现在我需要两个问题的帮助!
- 给定我的商店对象设置如何正确删除
- 为什么正确的饭菜不会删除
const store = {
meals: {
"Monday": [
{
"id": 1,
"recipe_id": 2,
"user_id": 1
},
{
"id": 2,
"recipe_id": 1,
"user_id": 1
},
{
"id": 3,
"recipe_id": 3,
"user_id": 1
}
],
"Tuesday": [
{
"id": 4,
"recipe_id": 4,
"user_id": 1
}
],
"Wednesday": [],
}
}
App.js 中的 deleteMeal
deleteMeal = (day, mealId) => {
this.setState(prevState => ({
// copy existing state
...prevState,
// update meals key
meals: {
// copy existing meals state
...prevState.meals,
// update day key & filter meals array by id
[day]: prevState.meals[day].filter( ({ id }) => id !== mealId),
}
}));
}
const contextValue = {
recipes: this.state.recipes,
meals: this.state.meals,
addRecipe: this.addRecipe,
deleteRecipe: this.deleteRecipe,
updateRecipe: this.updateRecipe,
addMeal: this.addMeal,
deleteMeal: this.deleteMeal
}
天数部分
class Days extends React.Component{
render() {
const { day, meals } = this.props
let mealsList;
if (meals[day]) {
mealsList = meals[day]
.map((meal, key) =>
<Meals
key={key}
day={day}
meal={meal}
/>
)
}
return(
<div className="Days">
<h3>{day}</h3>
{meals && meals[day] && mealsList}
</div>
)
}
}
膳食成分
class Meals extends React.Component {
static contextType = StashContext;
state = {
recipeTitle: 'No Title',
recipeImageUrl: '',
showModal: false
}
findRecipe = (recipeId, recipes) => {
const recipe = recipes.find( recipe => recipe.id == recipeId)
if (recipe) {
this.setState({
recipeTitle: recipe.title,
recipeImageUrl: recipe.image_url
})
}
}
componentDidMount() {
const { recipes } = this.context
const { meal } = this.props
this.findRecipe(meal.recipe_id, recipes)
}
handleClickDelete = (event) => {
const { day, meal } = this.props
const { id } = meal
event.preventDefault()
this.context.deleteMeal(day, id)
}
toggleModal = () => {
this.setState({
showModal: !this.state.showModal
})
}
render(){
const { recipeTitle, recipeImageUrl, showModal } = this.state;
const { meal } = this.props;
const customStyles = {
overlay: {
background: '#4c645682'
},
content: {
background: 'rgb(240 240 240)'
}
}
const permissions = {
edit: false,
add: false,
delete: false
}
return (
<div className="Meals">
{showModal &&
<DisplayModal
meal={meal}
customStyles={customStyles}
showModal={showModal}
closeModal={this.toggleModal}
label="Meal Modal"
permissions={permissions}
/>
}
<div className="Meals__info">
<div className="info_box left">
<div className="Meals__img">
<img src={recipeImageUrl} alt="Placeholder" />
</div>
</div>
<div className="info_box middle">
<div className="Meals__recipe-title">
{recipeTitle}
</div>
</div>
<div className="info_box right">
<div className="Meals__options">
<FontAwesomeIcon
icon={faEye}
onClick={e => {this.setState({showModal: true})}} />
<FontAwesomeIcon
icon={faBackspace}
onClick={this.handleClickDelete} />
</div>
</div>
</div>
</div>
)
}
}
export default Meals
解决方案
recipe id 似乎是多余的,我认为不需要,您应该可以删除一天中的餐点和 id。
这个想法是在您打算更新的每个级别上浅层复制状态对象。
deleteMeal = (day, mealId) => {
this.setState(prevState => ({
// copy existing state
...prevState,
// update meals key
meals: {
// copy existing meals state
...prevState.meals,
// update day key & filter meals array by id
[day]: prevState.meals[day].filter(({ id }) => id !== mealId),
},
}));
}
问题 - 不良反应键
您正在使用数组索引作为Days
组件中的反应键。
meals[day].map((meal, key) => (
<Meals
key={key} // <-- array index!!
day={day}
meal={meal}
/>
))
例如,如果您有一个包含三餐的数组,并且您删除了第一餐或第二餐,那么反应键仍然是索引 0 和 1。长度会改变,第三餐将不再呈现,但是因为前两个在重新渲染它们时没有改变反应保释。
如果项目的顺序可能发生变化,我们不建议对键使用索引。这会对性能产生负面影响,并可能导致组件状态出现问题。查看 Robin Pokorny 的文章, 深入解释使用索引作为键的负面影响。
链接文章的重要内容是此清单
- 列表和项目是静态的——它们不计算也不改变;
- 列表中的项目没有 ID;
- 该列表永远不会重新排序或过滤。
当所有这些都满足时,您可以安全地使用索引作为 key。
数组索引作为反应键在技术上是可以接受的,只要你不通过插入或删除元素来改变数组。由于您的meal
对象具有id
属性,因此应将其用于反应键。
meals[day].map(meal => (
<Meals
key={meal.id}
day={day}
meal={meal}
/>
))
推荐阅读
- python - 添加#noqa:F841后F841依然存在
- angular - Angular 8 网络工作者在 IE 中被破坏
- python - 在“pyenv/pyenv-virtualenv”中,我可以创建一个引用“system”的virtualenv,即之前没有“pyenv install”吗?
- angular - 如何在 mat-sidenav Angular 7 中引用正确的 routerlink?
- html - 我的 :hover 在 CSS 中只会影响我的 div/image
- linux - 如何使用“find”和“grep”来获取文件大小?
- html - CSS 过渡时间不适用于所有元素,li 和锚标签中的单词不会随着时间而缓和
- node.js - 带有快速请求的空白 PDF
- scala - 如何比较 3 个选项层次结构值并以 scala 方式返回布尔值?
- python - 如何在熊猫的多列中获得对行求和的百分比?