1

I would like to know as much as possible as to how this is working - especially as it relates to the usage of the ternary and the object argument containing two spreads.

rows = rows.map(row => (changed[row.ID] ? { ...row, ...changed[row.ID] } : row));

First - the objects being passed into the map are structured like this: changed is shaped like this {"75864":{"ActType":"DEADLINE"}}

rows is formatted like this (for example):

[{
    "ID": 75864,
    "NextDate": "2018-03-02T00:00:00",
    "NextTime": "1030am",
    "MatterID": 14116,
    "Descr": " Responses to pending discovery",
    "StatusID": 19,
    "Actor_s_": null,
    "Accrued": 0,
    "Go": "",
    "AspNetUserID": null,
    "DomainID": 2,
    "UserID": 1,
    "StatusType": "Pending",
    "ActTypeID": 50,
    "ActType": "DEADLINE",
    "MatterName": "WYNBAS                   "
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
user1836609
  • 75
  • 2
  • 10

2 Answers2

2

This is "merging" row and changed[row.ID] into a single object. Let's look at what happens when row is the one with the ID "75864":

// row: {"ID": 75864, "ActType": "DEADLINE", (more properties)}
// changed: {"75864": {"ActType": "OTHER ACTION"}}
// (Note - I changed `changed` so that the ActType specified is different from
//  what's already in the row object, otherwise it's really difficult for me to
//  demonstrate exactly what's happening here.)

// This is the body of the arrow function:
return changed[row.ID] ? { ...row, ...changed[row.ID] } : row

// Well, changed[row.ID] does exist:
// changed[row.ID]: {"ActType": "OTHER ACTION"}

// So we take this branch of the ternary:
return { ...row, ...changed[row.ID] }

// Basically, this expression works like an array spread, but for objects.
// As a refresher, here's what an array spread might look like:
//
// a = [1, 2, 3]
// b = ['cat', 'dog', 'armadillo']
// c = [...a, ...b]
// c: [1, 2, 3, 'cat', 'dog', 'armadillo']
//
// The array spread works by creating a completely new, empty array. Then
// it adds the items of each array that's spread into it; so first it adds
// all the items of a (1, 2, 3), then all the items of b (cat, dog, armadillo).

// Object spread works pretty much the same way. First we create a completely
// new object: {}.
// Then we add all the properties of row: {ID: 75864, ActType: "DEADLINE",
// "MatterID": 14116, (more properties)}.
// Then it adds the the properties of changed[row.ID]. This is the important
// part, because changed[row.ID] actually *overwrites* any properties that
// we've already added from "row". This makes the result look like this:
return {ID: 75864, ActType: "OTHER ACTION", MatterID: 14116, (more properties)}

// Note that the return value's ActType property is OTHER ACTION, not DEADLINE!

Note that object spread is essentially the same as using Object.assign with an empty object as the first argument. (Object.assign takes all the properties from the second, third, etc arguments and sets them on the first argument. That means it actually changes - mutates - its first argument; and here, we aren't mutating row, we're returning a totally new object based on row (and changed[row.ID]).) So writing your code with Object.assign would look like this:

return Object.assign({}, row, changed[row.ID])
Nebula
  • 6,614
  • 4
  • 20
  • 40
  • 1
    Thanks so much for this thorough answer! It completely covers what I needed to understand. Much appreciated, towerofnix! – user1836609 Feb 21 '18 at 14:26
0

IF the row.ID value matches a key which has "truthy" value in the changed object,

THEN you return a new object, with all values of the row (you spread the row), and you add to this new object the values of the matching changed object (you spread the truthy value of changed).

ELSE you simply return the given row.


Is it the answer your are looking for?

ChrisR
  • 3,922
  • 1
  • 14
  • 24