Skip to content

What is immutability?

Immutability means that once created, data cannot be changed. In contrast, mutable data can be modified after creation. JavaScript objects and arrays are mutable by default, but React and Redux expect all state updates to be done immutably.

ArcGIS Experience Builder uses the seamless immutable library to enforce immutability

Why use immutable objects?

ArcGIS Experience Builder is built using React and Redux which require immutable state updates for:

  • Predictable state changes: Immutable updates make it easier to track when and how state changes
  • Performance optimization: React can efficiently determine what needs to re-render
  • Debugging: Immutable data makes it easier to trace state changes and identify issues

Immutable types

By convention, all immutable types within Experience Builder start with IM:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
// Examples of immutable types
interface IMConfig {
  title: string;
  description: string;
}

interface IMDataSource {
  id: string;
  url: string;
  fields: string[];
}

Code examples

Update object properties of an immutable object

The following example shows how to update the properties of an immutable object.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { Immutable } from 'jimu-core';

// Create an immutable object
const config = Immutable({
  title: 'My Widget',
  settings: {
    theme: 'light',
    size: 'medium'
  }
});

// Update single property
const updatedConfig = config.set('title', 'Updated Widget');

// Update nested property
const nestedUpdate = config.setIn(['settings', 'theme'], 'dark');

// Merge multiple properties
const mergedConfig = config.merge({
  title: 'Merged Widget',
  settings: {
    size: 'large'
  }
});

The following table lists the methods available to update immutable objects.

MethodDescriptionExample
set()Set a single propertyobj.set('title', 'New Title')
setIn()Set nested propertiesobj.setIn(['user', 'name'], 'John')
merge()Merge multiple propertiesobj.merge({title: 'New', active: true})

Add items to an array

The following example shows how to add items to an immutable array.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
// Recommended approach
const newArray = Immutable(
  array.concat(Immutable([newItem]))
);

// Alternative approach (when you need multiple operations)
let mutableArray = array.asMutable();
mutableArray.push(newItem);
const immutableArray = Immutable(mutableArray);

Remove items from an array

The following example shows how to remove items from an immutable array.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
// Remove item by ID
const filteredArray = array.flatMap(item =>
  item.id === itemToRemove ? [] : [item]
);

// Remove item by index
const indexToRemove = 2;
const arrayWithoutItem = array.flatMap((item, index) =>
  index === indexToRemove ? [] : [item]
);

Update items in an array

The following example shows how to update items in an immutable array.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Update item by index
const updatedArray = array.map((item, index) => {
  if (index === targetIndex) {
    return item.set('property', newValue);
  }
  return item;
});

// Update item by condition
const updatedByCondition = array.map(item => {
  if (item.id === targetId) {
    return item.merge({
      title: 'Updated Title',
      modified: true
    });
  }
  return item;
});

Performance considerations

The following example shows how and when to use asMutable() when you need to perform multiple operations.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Good: Multiple operations
let mutableArray = array.asMutable();
mutableArray.push(item1);
mutableArray.push(item2);
mutableArray.sort((a, b) => a.name.localeCompare(b.name));
const finalArray = Immutable(mutableArray);

// Avoid: Single operations
let mutableArray = array.asMutable();
mutableArray.push(item);
const finalArray = Immutable(mutableArray);

// If in large loop, use .merge():
const imObject = obj
const modifierObject = {}
// Example large loop:
for (let i = 0; i < 100000; i ++) {
  modifierObject[i] = 'some value'
}
const imNewObject = imObject.merge(modifierObject)

Performance best practices

The following table lists the performance best practices for immutable objects.

ScenarioRecommended ApproachReason
Single property updateset() or setIn()Most efficient
Multiple property updatesmerge()Reduces object creation
Array filteringflatMap()Functional approach
Multiple array operationsasMutable() then Immutable()Reduces intermediate objects
Deep object updatessetIn()Avoids deep cloning

Resources

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.