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:
// 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.
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.
| Method | Description | Example |
|---|---|---|
set() | Set a single property | obj.set('title', ' |
set | Set nested properties | obj.set |
merge() | Merge multiple properties | obj.merge({title |
Add items to an array
The following example shows how to add items to an immutable array.
// 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.
// 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.
// 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 as when you need to perform multiple operations.
// 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.
| Scenario | Recommended Approach | Reason |
|---|---|---|
| Single property update | set() or set | Most efficient |
| Multiple property updates | merge() | Reduces object creation |
| Array filtering | flat | Functional approach |
| Multiple array operations | as then Immutable() | Reduces intermediate objects |
| Deep object updates | set | Avoids deep cloning |