How to set value of an immutable state in Javascript?

immutable javascript
mutable and immutable data types in javascript
immutable js typescript
immutable js tutorial
immutable javascript example
javascript immutable library
javascript immutable object copy
immutable functions in javascript

Given an immutable state like this:

alerts: {
  5a8c76171bbb57b2950000c4: [
    {
      _id:5af7c8652552070000000064
      device_id:5a8c76171bbb57b2950000c4
      count: 1
    },
    {
      _id:5af7c8722552070000000068
      device_id:5a8c76171bbb57b2950000c4
      count: 2
    }
  ]
}

and an object like this:

{
   _id:5af7c8652552070000000064
   device_id:5a8c76171bbb57b2950000c4
   count: 2
}

I want to replace the object with the same id in the alerts state (immutable), such that end result looks like this:

alerts: {
  5a12356ws13tch: [
    {
      _id:5af7c8652552070000000064
      device_id:5a8c76171bbb57b2950000c4
      count: 2
    },
    {
      _id:5af7c8722552070000000068
      device_id:5a8c76171bbb57b2950000c4
      count: 2
    }
  ]
}

How can I do that? With mergeDeep, getIn, setIn, and updateIn, found on List, Map or OrderedMap ?

I tried doing something like this.. where index is 0 and deviceId is 5a12356ws13tch

Does not work though.

export const oneAlertFetched = (state, {deviceId, index, alert}) => state.setIn(['alerts', deviceId, index], alert).merge({fetching: false})

I tried this as well. Does not work.

export const oneAlertFetched = (state, {deviceId, index, alert}) => {
  const a = state.alerts[deviceId][index]
  state.alerts[deviceId][index] = Object.assign({}, a, alert)
  return
}

I think you mean you want to return a new object with the updated payload?

function getNextAlerts(alerts, parentDeviceId, payload) {
  const alertsForDevice = alerts[parentDeviceId];
  
  if (!alertsForDevice || alertsForDevice.length === 0) {
     console.log('No alerts for device', deviceId);
     return;
  }

  return {
    ...alerts,
    [parentDeviceId]: alerts[parentDeviceId].map(item =>
      item._id === payload._id ? payload : item
    ),
  }
}

const alerts = {
  '5a12356ws13tch': [
    {
      _id: '5af7c8652552070000000064',
      device_id: '5a8c76171bbb57b2950000c4',
      count: 1
    },
    {
      _id: '5af7c8722552070000000068',
      device_id: '5a8c76171bbb57b2950000c4',
      count: 2
    }
  ]
};

const nextAlerts = getNextAlerts(alerts, '5a12356ws13tch', {
   _id: '5af7c8652552070000000064',
   device_id: '5a8c76171bbb57b2950000c4',
   count: 2,
});

console.log('nextAlerts:', nextAlerts);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Immutability in JavaScript, In programming, we use the word to mean objects whose state is allowed to change over time. An immutable value is the exact opposite – after  2 Answers 2. state should be a plain JavaScript object as you can read in the documentation. Note that state must be a plain JS object, and not an Immutable collection, because React's setState API expects an object literal and will merge it (Object.assign) with the previous state.


By immutable, you mean that your property is non-writable.

If you want to modify your object in-place (not recommended), you will need the property to be at least configurable:

const device = alerts['5a12356ws13tch'][0];

if (Object.getOwnPropertyDescriptor(device, 'count').configurable) {
    // Manually make it `writable`
    Object.defineProperty(device, 'count', {
        writable: true
    });

    // Update property's value
    device.count++;

    // Set it back to `non-writable`
    Object.defineProperty(device, 'count', {
        writable: false
    });
}
console.log(device.count); // 2

If it is not configurable (cannot make it writable), or you do not want to jeopardize your application (it must be non-writable on purpose), then you should work on copies.

const device = alerts['5a12356ws13tch'][0];
alerts['5a12356ws13tch'][0] = Object.assign({}, device, {count: device.count + 1});

Object.assign() works on flat objects. If you need deep copy, have a look at my SO answer there.

Four Ways to Immutability in JavaScript, Accordingly, a JS developer must take special care if they intend to number, string, and symbol values) are immutable by default, so you In strict mode, attempting to set a property on a frozen object throws a helpful error. This principle is most important to understanding the appropriate use of immutable data. In order to treat Immutable.js collections as values, it's important to use the Immutable.is () function or .equals () method to determine value equality instead of the === operator which determines object reference identity.


If you're working with plain JavaScript objects and want to keep "immutable" approach you have to use spreads all over the nested structure of state object.

But, there are some tools already targeting this issue - lenses.

Here is the example of both approaches, array/object spreads and lenses - ramda repl.

In short, your example via spreads:

const oneAlertFetched = (state, { deviceId, index, alert }) => ({
  ...state,
  alerts: {
    ...state.alerts,
    [deviceId]: [
      ...state.alerts[deviceId].slice(0, index),
      { ...state.alerts[deviceId][index], ...alert },
      ...state.alerts[deviceId].slice(index + 1)
    ],
  }
})

And via lenses using Ramda's over, lensPath, merge and __*:

const oneAlertFetched = (state, { deviceId, index, alert }) =>
  R.over(
    R.lensPath(['alerts', deviceId, index]),
    R.merge(R.__, alert),
    state
  )

* R.__ placeholder used to swap 1st & 2nd parameters of R.merge

PS: lenses solution is intentionally adjusted to match the declaration of your function, so you can easily compare two approaches. However, in real life, with such powerful and flexible tool, we can rewrite the function to be more readable, reusable, and performant.

Easy immutable objects in Javascript, Immutable means that the state should be an object that does not change new one from scratch by modifying and copying the previous state values. (​considering how quickly the Javascript framework state change) but the  Even simple state changes, normally done with two-way binding (e.g. v-model in Vue or ngModel in Angular), could benefit from the immutable approach. We do this by making a copy of the component’s input, mutating the copy and output the mutated copy to the caller.


Immutable.js, Immutable collections should be treated as values rather than objects. While objects represent some thing which could change over time, a value represents the  But there's also the concept of "value equality," where you can check if two objects are identical by doing obj1.equals (obj2). When things are immutable, you treat objects as just values. In ClojureScript everything is a value, and even the default equality operator performs the value equality check (as if === would).


— Immutable.js, In order to better explain what kinds of values the Immutable.js API expects and A record is similar to a JS object, but enforces a specific set of allowed string  In the following, I’ll do a quick introduction on how to keep your state objects immutable using modern Javascript techniques, I’ll present how complex it is to modify non-trivial immutable objects and finally I’ll give you a quick recipe for modifying your non-trivial immutable objects.


Handling State in React: Four Immutable Approaches to Consider, Line 4 actually mutates state because the user variable is a this.state = { // Create an immutable map in state using immutable.js user: Map({  Immutability in JavaScript in Practice JavaScript doesn’t (yet) have immutable lists and maps, so we’ll need a third-party library for now. There are two very good ones available.