0

This is confusing me to no end. I am trying to update an objects property dynamically based on vars provided by another function however, when I update the property it updates all the same nested properties of the parent object.

export type TopContributing = {
  totalInTopFive: number
  one: BreakdownForName
  two: BreakdownForName
  three: BreakdownForName
  four: BreakdownForName
  five: BreakdownForName
  others: BreakdownForName
}

export type BreakdownForName = {
  name: string
  itemBreakdown: {
    cancelled: MetricValue
    outstanding: MetricValue
    reclassifiedAsIssue: MetricValue
    reclassifiedAsValid: MetricValue
  }
}

type MetricValue = { 
    items: object[]; 
    count: number 
}

const populateTopOutcomes = (
  item: object, //the object to push to topItems
  outcome: string, //the itemBreakdown property e.g. outstanding, reclassifiedAsValid, etc.
  topItems: TopContributing, // the parent Object that contains Top5Items, others and totalCount.
  topFive: string[] // list of names of top items
) => {
  const itemIndex = topFive.indexOf(item.name) // find index of which bucket in topItems the item's in
  if (itemIndex === 0) {
    topItems.one.itemBreakdown[outcome].items.push(item)
    topItems.one.itemBreakdown[outcome].count++
  }
  else if (itemIndex === 1)  {
    topItems.two.itemBreakdown[outcome].items.push(item)
    topItems.two.itemBreakdown[outcome].count ++
  }
  else if (itemIndex  === 2)  {
    topItems.three.itemBreakdown[outcome].items.push(item)
    topItems.three.itemBreakdown[outcome].count ++
  }
  else if (itemIndex  === 3)  {
    topItems.four.itemBreakdown[outcome].items.push(item)
    topItems.four.itemBreakdown[outcome].count ++
  }
  else if (itemIndex  === 4)  {
    topItems.five.itemBreakdown[outcome].items.push(item)
    topItems.five.itemBreakdown[outcome].count ++
  }
  else if (itemIndex  < 0)  {
    topItems.others.itemBreakdown[outcome].items.push(item)
    topItems.others.itemBreakdown[outcome].count ++
  }
}

The issue I run into is when I access the MetricValue object in topItems.{property}.itemBreakdown[outcome] using outcome, it updates that property (items or count) in all of the objects in the TopContributing object. For Example if I try to update outcome "outstanding" in topItems.one it will add that same value to topItems.two, three, etc. What's going on? I can't figure out why this happens. Any help would be great!

Haq.H
  • 863
  • 7
  • 20
  • 47
  • 3
    Please show where you're setting `topItems.one`, `topItems.two`, etc. You're likely setting them all to the same object. – Heretic Monkey Apr 02 '20 at 19:28
  • 1
    @HereticMonkey is right, you are setting the properties to an object, if you want to start with all of the same data but not have them all change together, you should use a cloning technique (such as the spread operator) which gives all the same data, but not the same actual object reference. – Cal Irvine Apr 02 '20 at 19:30
  • 3
    To add to Heretic Monkey's comment, specifically the *same object reference*. So when using the reference to mutate the object you are mutating the original and all refs point to it. – Drew Reese Apr 02 '20 at 19:30
  • in the function populateTopOutcomes. I pass in the parent object in this case topItems and I want to mutate one of it's properties based the item index I calculate in that function. In The code above: this line "topItems.one.itemBreakdown[outcome].items.push(item)" will update the items in topItems.one, topItems.two, topItems.three and so on. I don't think I am accessing the same object here. – Haq.H Apr 02 '20 at 19:33
  • Nvm I think I might know what's going on @CalIrvine made a good point. I am using a helper to initialize an empty object but the empty objects inside are not unique. That makes sense. THANK YOU – Haq.H Apr 02 '20 at 19:36

0 Answers0