Updating Copies Of Data in Javascript Without Changing Original Source

Updating Copies Of Data in Javascript Without Changing Original Source

Sometimes we need to mutate copies of data in javascript and working on it without altering the original source, so in this article we will take a look at two important npm packages to achieve this.

 

 

 

Javascript applications such as applications built on Reactjs or Vuejs needs a way to update state by making copy of it without altering the original source. If you with React or Vue before you will see that when you need to update state the only way is to copy the original state, then update and finally return the updated state.

To update state the classic way most people follow is using Object.assign() to copy the object and work on it.

consider this example:

const obj1 = {x: 1, y: 1};

Now we need to alter this object by modifying x to 5 we can use Object.assign():

const obj2 = Object.assign({}, obj1);
obj2.x = 5;
console.log(obj2, obj1);

// Object { x: 5, y: 1 }
 
// Object { x: 1, y: 1 }

This is a trivial example but consider this complex object:

let state = {
    products: [
        {id: 1, name: 'product 1', price: 20},
        {id: 2, name: 'product 2', price: 30},
        {id: 3, name: 'product 3', price: 10}
    ],
    show_spinner: false,
    user_data: {
         name: 'Wael Salah',
         email: 'admin@email.com',
         age: 25
    }
};

Now if need to alter this object products second element, using Object.assign() is a tedious task. To overcome these situations we will use either of these packages immutability-helper or updeep

 

Immutability Helper

To install immutability-helper via npm

npm install immutability-helper --save

Usage

import update from 'immutability-helper';

Simple Push

const initialArray = [1, 2, 3];
const newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]

Nested collections

const collection = [1, 2, {a: [12, 17, 15]}];
const newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
// => [1, 2, {a: [12, 13, 14, 15]}]

(Shallow) Merge

const obj = {a: 5, b: 3};
const newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}

Removing an element from an array

// Delete at a specific index, no matter what value is in it
update(state, { items: { $splice: [[index, 1]] } });

Autovivification

Auto creation of new arrays and objects when needed

const state = {}
state.a.b.c = 1; // state would equal { a: { b: { c: 1 } } }

 

Full list of commands

  • {$push: array} push() all the items in array on the target.
  • {$unshift: array} unshift() all the items in array on the target.
  • {$splice: array of arrays} for each item in arrays call splice() on the target with the parameters provided by the item. Note: The items in the array are applied sequentially, so the order matters. The indices of the target may change during the operation.
  • {$set: any} replace the target entirely.
  • {$toggle: array of strings} toggles a list of boolean fields from the target object.
  • {$unset: array of strings} remove the list of keys in array from the target object.
  • {$merge: object} merge the keys of object with the target.
  • {$apply: function} passes in the current value to the function and updates it with the new returned value.
  • {$add: array of objects} add a value to a Map or Set. When adding to a Set you pass in an array of objects to add, when adding to a Map, you pass in [key, value] arrays like so: update(myMap, {$add: [['foo', 'bar'], ['baz', 'boo']]})
  • {$remove: array of strings} remove the list of keys in array from a Map or Set.

 

Udeep

To install udeep via npm:

npm install --save updeep

udeep provides similar methods like immutability-helper.

Usage

var u = require('updeep');

Simple update

var person = {
  name: {
    first: 'Jane',
    last: 'West'
  }
};

var result = u({ name: { first: 'Susan' } }, person);

var scoreboard = {
  scores: [12, 28]
};

var result = u({ scores: { 1: 36 } }, scoreboard);

Multiple updates

var person = {
  name: {
    first: 'Mike',
    last: 'Smith'
  },
  scores: [12, 28]
};

var result = u({ name: { last: 'Jones' }, scores: { 1: 36 } }, person);

Use a function

function increment(i) { return i + 1; }
var scoreboard = {
  scores: {
    team1: 0,
    team2: 0
  }
};

var result = u({ scores: { team2: increment } }, scoreboard);

ES6 computed properties

var key = 'age';

var result = u({ person: { [key]: 21 } }, { person: { name: 'Olivier P.', age: 20 } });

For a full list of commands refer to udeep github page.

 

 

0 0 vote
Article Rating
Share this: