[英]React state - updating property on object in nested array
I have a React app with an interface that allows users to select a date and time slot. 我有一个带有界面的React应用程序,该界面允许用户选择日期和时间段。 I have a top level object that maintains the state, which might look like this:
我有一个维护状态的顶级对象,可能看起来像这样:
this.state = {
days: [{
date: '12-13-2022',
time_slots: [{
start: '10 am',
end: '11 am',
selected: false
},{
start: '1 pm',
end: '3 pm',
selected: false
}]
}, {
date: '12-14-2022',
time_slots: [{
start: '10 am',
end: '11 am',
selected: false
}
}]
}
When a user clicks on a time slot, I want to update the selected
property to true
. 当用户单击时隙时,我想将
selected
属性更新为true
。
So far I have this, but I think I'm mutating the state, which is bad practice. 到目前为止,我已经知道了,但是我认为我正在改变状态,这是一种不好的做法。
slotClicked(day_index, slot_index) {
let state = this.state.days[day_index].time_slots[slot_index].selected = true;
this.setState({state});
}
How might I update the state in an efficient (in terms of re-rendering) and immutable way? 如何以有效的方式(在重新渲染方面)和不变的方式更新状态?
You have to deep clone your array, in opposition to other answers: 与其他答案相反,您必须深度克隆数组:
slotClicked(day_index, slot_index) {
// If you prefer you can use lodash method _.cloneDeep()
const newDays = JSON.parse(JSON.stringify(this.state.days));
newDays[day_index].time_slots[slot_index].selected = true;
this.setState({days: newDays});
}
If you do not deep clone your array, the time_slots
array will be copied by reference and mutanting it will mutate original array in state. 如果不深度克隆数组,则
time_slots
数组将通过引用进行复制,并且对其进行突变会使状态为原始数组发生变异。
You can make use of Array.map function as, 您可以将Array.map函数用作
slotClicked(day_index,slot_index){
let current_state = this.state;
this.state.days.map((days,days_index) => {
if(days_index===day_index){
// console.log("day",days);
let newSlot = '';
days.time_slots.map((time_slot,slots_index)=>{
if(slots_index===slot_index){
// console.log("time",time_slot);
newSlot = Object.assign({},time_slot,{selected:true});
}
})
// console.log("new slot",newSlot);
days.time_slots[slot_index] = newSlot;
this.setState({days:current_state},()=>{
console.log(this.state);
});
}
});
}
To update a deeply nested data, you can use https://github.com/debitoor/dot-prop-immutable or something similar. 要更新深度嵌套的数据,可以使用https://github.com/debitoor/dot-prop-immutable或类似的方法。 In plain Javascript, it will be more verbose like below
在普通的Javascript中,它将变得更加冗长,如下所示
const state = this.state;
const newState = {
...state,
days: [
...state.days.slice(0, day_index),
{
...state.days[day_index],
time_slots: [
...state.days[day_index].time_slots.slice(0, slot_index),
{...state.days[day_index].time_slots[slot_index], selected: true},
...state.days[day_index].time_slots.slice(slot_index + 1)
]
},
...state.days.slice(day_index + 1)
]
}
try this, here we are cloning previous state and updating the new one 试试这个,这里我们正在克隆以前的状态并更新新的状态
slotClicked(day_index, slot_index) {
let newStateDays = [...this.state.days]
newStateDays[day_index].time_slots[slot_index].selected = true;
this.setState({days: newStateDays});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.