Immutable in React Gantt Chart component
4 Jul 20267 minutes to read
Immutable mode optimizes the React Gantt Chart component’s rendering performance by minimizing unnecessary re-renders, ideal for large projects with hundreds of tasks or frequent updates like real-time progress tracking. When enabled via the enableImmutableMode property, the component uses object reference comparison to identify changed tasks, re-rendering only modified or new rows while preserving unchanged rows’ DOM elements. This reduces DOM operations, CPU usage, and rendering time, ensuring smooth interactions for complex hierarchies or batch updates. For example, updating a single task’s progress in a 1,000-task project re-renders only that task’s row, significantly improving performance over standard mode, which re-renders all visible rows.
Configure immutable mode
Immutable mode requires a unique primary key in the data source, configured via the isPrimaryKey property, and valid taskFields mappings (e.g., id to a unique field like TaskID). The component compares object references to detect changes, requiring immutable data patterns where updates create new objects rather than mutating existing ones. Hierarchical task updates (e.g., parent-child tasks) are efficiently handled by checking only changed references, preserving nested structures.
Configuration requirements
-
Primary key: Set
isPrimaryKeyto true on a unique column (e.g., TaskID) to ensure accurate change detection. -
Unique identifiers: Assign stable, unique IDs to all tasks via
taskFields.id. - Immutable data: Create new objects for updates (e.g., { …task, progress: 50 }) to trigger reference changes.
The following example enables immutable mode:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject,Selection,Toolbar, ToolbarItem, Edit, EditSettingsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App(){
const taskFields = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID',
};
const editOptions = {
allowAdding: true,
allowEditing: true,
allowDeleting: true
};
const toolbarOptions = ['Add','Edit','Delete','Cancel','Update','PrevTimeSpan','NextTimeSpan','ExpandAll','CollapseAll','Search','Indent','Outdent'];
return <GanttComponent dataSource={data} taskFields={taskFields} enableImmutableMode={true}
height = '450px' editSettings={editOptions} toolbar={toolbarOptions}>
<Inject services={[Selection, Toolbar, Edit]} />
</GanttComponent>
};
ReactDOM.render(<App />, document.getElementById('root'));import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Selection, Toolbar, ToolbarItem, Edit, EditSettingsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
const taskFields: any = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID',
};
const editOptions: EditSettingsModel = {
allowAdding: true,
allowEditing: true,
allowDeleting: true
};
const toolbarOptions: ToolbarItem[] = ['Add', 'Edit', 'Delete', 'Cancel', 'Update', 'PrevTimeSpan', 'NextTimeSpan', 'ExpandAll', 'CollapseAll', 'Search', 'Indent', 'Outdent'];
return <GanttComponent dataSource={data} taskFields={taskFields} enableImmutableMode={true}
height='450px' editSettings={editOptions} toolbar={toolbarOptions}>
<Inject services={[Selection, Toolbar, Edit]} />
</GanttComponent>
};
ReactDOM.render(<App />, document.getElementById('root'));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>Feature compatibility and limitations
Immutable mode is incompatible with certain features due to its reference-based change detection:
-
Column reordering: Conflicts with reference tracking, requiring temporary disabling of
enableImmutableMode. - Virtualization: Incompatible with enableVirtualization, as both optimize rendering differently; choose based on dataset size.
For small datasets, standard rendering may suffice. For dynamic column operations, disable immutable mode temporarily. While immutable mode reduces rendering time, it may increase memory usage to maintain object references, a trade-off to consider for extremely large projects.