我有嵌套的对象,并且在传入更改时,我想创建费用对象的副本并更新所有timeSpent值。新值是根据更新后的数据计算得出的,因此我必须对每个timeSpent值进行计算。我找不到解决办法。
我已经厌倦了使用{... expenses.byId}创建费用对象的副本,并使用Ovject.values从中创建数组,映射数据并进行计算。然后问题出现了,值被嵌套,所以原始对象被更改了。
我很累于制作对象的深层副本,问题是否相同或我做错了什么。如果我需要在copyOfExpenses中更深入一点,该怎么做?
const state = {
expenses: {
byId: {
k948zpnp: {
id: 'k948zpnp',
category: 'other',
description: 'book',
amount: '25',
timeSpent: '2.5',
time: '2020-4-21 10:48:10'
},
z9e8ipnp: {
id: 'z9e8ipnp',
category: 'food',
description: 'pasta',
amount: '12',
timeSpent: '1.2',
time: '2020-4-21 11:48:10'
},
},
allIds: ['k948zpnp', 'z9e8ipnp']
}
}
const copyOfExpenses = {
...state,
expenses: {
...state.expenses,
byId: { ...state.expenses.byId },
allIds: [...state.expenses.allIds]
}
}
let newInputForTimeSpent = 14
let newData = copyOfExpenses.expenses.allIds.map(
item =>
(copyOfExpenses.expenses.byId[item].timeSpent =
copyOfExpenses.expenses.byId[item].timeSpent * newInputForTimeSpent)
)
console.log(copyOfExpenses) // changes works
console.log(state) // original data gets changed
答案 0 :(得分:1)
第一种方法
我知道,对ID进行硬编码是一个糟糕的主意。
let newInputForTimeSpent = 14;
const copyOfExpenses = {
...state,
expenses: {
...state.expenses,
byId: {
...state.expenses.byId,
k948zpnp: {
...state.expenses.k948zpnp,
timeSpent: state.expenses.k948zpnp.timeSpent * newInputForTimeSpent
},
z9e8ipnp: {
...state.expenses.z9e8ipnp,
timeSpent: state.expenses.z9e8ipnp.timeSpent * newInputForTimeSpent
}
},
allIds: [...state.expenses.allIds]
}
}
第二种方法
const state = {
expenses: {
byId: {
k948zpnp: {
id: 'k948zpnp',
category: 'other',
description: 'book',
amount: '25',
timeSpent: '2.5',
time: '2020-4-21 10:48:10'
},
z9e8ipnp: {
id: 'z9e8ipnp',
category: 'food',
description: 'pasta',
amount: '12',
timeSpent: '1.2',
time: '2020-4-21 11:48:10'
},
},
allIds: ['k948zpnp', 'z9e8ipnp']
}
}
const updateTimeSpentForExpenses = (state, newInputForTimeSpent) => {
let byId = { ...state.expenses.byId
}
const newObjs = Object.entries(byId).map(([key, value]) => {
return {
[key]: {
...value,
timeSpent: value.timeSpent * newInputForTimeSpent
}
}
})
for (let newObj of newObjs) {
Object.assign(byId, newObj)
}
return {
...state,
expenses: {
...state.expenses,
byId,
allIds: [...state.expenses.allIds]
}
}
}
console.log(updateTimeSpentForExpenses(state, 10))
您可以使用for of loop
代替Object.assign
和Array.reduce
const newObjs = Object.entries(byId).map(([key, value]) => {
return {
[key]: {
...value,
timeSpent: value.timeSpent * newInputForTimeSpent
}
}
})
for(let newObj of newObjs) {
Object.assign(byId, newObj)
}
成为
byId = Object.entries(byId).map(([key, value]) => {
return [key, {
...value,
timeSpent: value.timeSpent * newInputForTimeSpent
}]
}
}).reduce((acc, ([key, value]) => {
acc[key] = value;
return acc;
}, {})