Обновление нескольких вложенных объектов - PullRequest
2 голосов
/ 22 апреля 2020

У меня есть вложенный объект, и при входящем изменении я хочу создать копию объекта расходов и обновить все значения timeSpent . Новые значения рассчитываются на основе обновленных данных, поэтому я должен выполнить расчет для каждого значения timeSpent. Я не могу найти способ сделать это.

Мне надоело создавать копию объекта расходов с помощью {... cost.byId} и создавать из него массив с Ovject.values, отображать данные и делать расчеты. Затем возникает проблема, значения вкладываются, поэтому оригинальный объект изменяется.

Я устал делать глубокую копию объекта, проблема та же или я делаю что-то не так. Если мне нужно go на один уровень глубже в 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

1 Ответ

1 голос
/ 22 апреля 2020

Первый подход

Я знаю, жесткие коды - ужасная идея.

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;
}, {})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...