React Gantt Hooks
The @dhx/react-gantt wrapper provides a set of React hooks that bridge your components to Gantt's internal APIs without requiring direct access to the Gantt instance. These hooks handle lifecycle management automatically - subscriptions are created on mount and cleaned up on unmount.
All hooks accept a ganttRef parameter - a React ref to the ReactGantt component:
import { useRef } from 'react';
import ReactGantt, { ReactGanttRef } from '@dhx/react-gantt';
function MyGanttApp() {
const ganttRef = useRef<ReactGanttRef>(null);
// pass ganttRef to any hook
return <ReactGantt ref={ganttRef} tasks={tasks} links={links} />;
}
useGanttEvent
Subscribe to a Gantt event with automatic lifecycle management. Attaches the handler on mount and detaches on unmount.
import { useGanttEvent } from '@dhx/react-gantt';
Signature:
useGanttEvent(ganttRef, eventName, handler, options?)
Parameters:
ganttRef- ref to the ReactGantt componenteventName- the Gantt event name (e.g.,'onAfterTaskUpdate','onStoreUpdated')handler- callback functionoptions.target- (optional) accessor function that resolves the event source from the Gantt instance. When omitted, events attach to the Gantt instance itself.
Works with any object that implements attachEvent/detachEvent - the Gantt instance, extensions, datastores, and UI modules:
import { useGanttEvent } from '@dhx/react-gantt';
function MyComponent({ ganttRef }) {
// Gantt instance events (default target)
useGanttEvent(ganttRef, 'onAfterTaskUpdate', (id, task) => {
console.log('Task updated:', id);
});
// Extension events - pass a target accessor
useGanttEvent(ganttRef, 'onAfterZoom', (level) => {
console.log('Zoomed to level:', level);
}, { target: (gantt) => gantt.ext.zoom });
// Datastore events
useGanttEvent(ganttRef, 'onStoreUpdated', () => {
console.log('Resource store changed');
}, { target: (gantt) => gantt.getDatastore('resource') });
return null;
}
If the event or target is not available (e.g., a plugin is not enabled), the hook silently does nothing.
useResourceAssignments
Access Gantt's resource assignment and resource management methods.
import { useResourceAssignments } from '@dhx/react-gantt';
Returns:
getResourceAssignments(resourceId, taskId?)- bridge to . Returns assignments for a resource, optionally filtered by task.getTaskResources(taskId)- bridge to . Returns unique resources assigned to a task.getTaskAssignments(taskId)- bridge to . Returns all assignments for a task.getAllResources()- returns all items from the resource datastore.setTaskAssignments(taskId, assignments)- replaces all assignments for a task. Each assignment should haveresource_idand optionallyvalue.
import { useResourceAssignments } from '@dhx/react-gantt';
function ResourcePanel({ ganttRef, taskId }) {
const { getTaskAssignments, getAllResources, setTaskAssignments } =
useResourceAssignments(ganttRef);
const assignments = getTaskAssignments(taskId);
const resources = getAllResources();
function reassign() {
setTaskAssignments(taskId, [
{ resource_id: 1, value: 8 },
{ resource_id: 3, value: 4 }
]);
}
return (
<div>
<p>Assigned: {assignments.map(a => a.resource_id).join(', ')}</p>
<p>Available: {resources.map(r => r.text).join(', ')}</p>
<button onClick={reassign}>Reassign</button>
</div>
);
}
useGanttDatastore
Read-only access to any Gantt datastore - tasks, links, resources, assignments, baselines, or custom stores.
import { useGanttDatastore } from '@dhx/react-gantt';
Signature:
const store = useGanttDatastore<T>(ganttRef, storeName)
Returns:
getItem(id)- returns a single item by IDgetItems()- returns all itemshasChild(id)- checks if an item has children (tree datastores)getChildren(id)- returns child IDs (tree datastores)eachItem(callback)- iterates through all items in the datastorefind(filter)- returns items matching a predicate functioncount()- returns total number of itemsexists(id)- checks if an item exists
import { useGanttDatastore, ResourceItem } from '@dhx/react-gantt';
function ResourceList({ ganttRef }) {
const store = useGanttDatastore<ResourceItem>(ganttRef, 'resource');
// Find all leaf (non-group) resources
const individuals = store.find(r => !store.hasChild(r.id));
// Iterate all resources
store.eachItem(resource => {
console.log(resource.text, store.hasChild(resource.id) ? '(group)' : '');
});
return (
<ul>
{individuals.map(r => <li key={r.id}>{r.text}</li>)}
</ul>
);
}
useUndoRedo
Track undo/redo stack state and provide actions. Automatically subscribes to task and link change events to keep state current.
import { useUndoRedo } from '@dhx/react-gantt';
Returns:
canUndo-boolean, true when the undo stack is non-emptycanRedo-boolean, true when the redo stack is non-emptyundo()- performs an undo operationredo()- performs a redo operation
Returns disabled state (canUndo: false, canRedo: false) if the undo plugin is not enabled.
import { useUndoRedo } from '@dhx/react-gantt';
function UndoRedoButtons({ ganttRef }) {
const { canUndo, canRedo, undo, redo } = useUndoRedo(ganttRef);
return (
<div>
<button onClick={undo} disabled={!canUndo}>Undo</button>
<button onClick={redo} disabled={!canRedo}>Redo</button>
</div>
);
}
The undo plugin must be enabled in the plugins prop for this hook to work:
<ReactGantt plugins={{ undo: true }} ... />
useZoom
Manage timeline zoom levels and track the current zoom state. Initializes the zoom extension automatically.
import { useZoom } from '@dhx/react-gantt';
Signature:
const zoom = useZoom(ganttRef, levels?)
Parameters:
ganttRef- ref to the ReactGantt componentlevels- (optional) array of zoom level configurations. Defaults to 5 built-in levels: Day, Week, Month, Quarter, Year.
Returns:
currentLevel- name of the active zoom levellevels- the zoom level configurationszoomIn()- zoom to a more detailed levelzoomOut()- zoom to a less detailed levelsetLevel(name)- jump to a specific zoom level by name
import { useZoom } from '@dhx/react-gantt';
function ZoomControls({ ganttRef }) {
const { currentLevel, levels, zoomIn, zoomOut, setLevel } = useZoom(ganttRef);
return (
<div>
<button onClick={zoomOut}>-</button>
<select value={currentLevel} onChange={e => setLevel(e.target.value)}>
{levels.map(l => (
<option key={l.name} value={l.name}>{l.label || l.name}</option>
))}
</select>
<button onClick={zoomIn}>+</button>
</div>
);
}
You can provide custom zoom levels:
const customLevels = [
{
name: 'sprint',
label: 'Sprint (2 weeks)',
scale_height: 60,
min_column_width: 70,
scales: [
{ unit: 'month', step: 1, format: '%F %Y' },
{ unit: 'week', step: 2, format: 'Sprint %W' },
],
},
// ...more levels
];
const zoom = useZoom(ganttRef, customLevels);
useSelection
Track which task is currently selected in the Gantt chart.
import { useSelection } from '@dhx/react-gantt';
Returns:
selectedId- the ID of the currently selected task, ornullif nothing is selected
import { useSelection } from '@dhx/react-gantt';
function TaskDetails({ ganttRef }) {
const { selectedId } = useSelection(ganttRef);
if (!selectedId) return <p>Select a task to see details.</p>;
return <p>Selected task: {selectedId}</p>;
}
useWorkTime
Bridge to Gantt's built-in work time calculation functions. Use this for highlighting non-working time and for date arithmetic that respects work calendars.
import { useWorkTime } from '@dhx/react-gantt';
Returns:
isWorkTime({ date, unit?, task? })- bridge tocalculateEndDate({ start, duration, unit?, task? })- bridge tocalculateDuration({ start, end, task? })- bridge togetClosestWorkTime({ date, unit, task?, dir? })- bridge to
import ReactGantt, { GanttTemplates, ReactGanttRef, useWorkTime } from '@dhx/react-gantt';
function GanttWithWeekends() {
const ganttRef = useRef<ReactGanttRef>(null);
const { isWorkTime } = useWorkTime(ganttRef);
const templates: GanttTemplates = {
timeline_cell_class: (task, date) => {
return isWorkTime({ date, task }) ? '' : 'weekend';
}
};
return <ReactGantt ref={ganttRef} templates={templates} tasks={tasks} />;
}
Composing hooks
Build domain-specific hooks by composing the built-in hooks. For example, a resource histogram hook:
import { useMemo, useCallback } from 'react';
import { useGanttDatastore, useResourceAssignments, useWorkTime } from '@dhx/react-gantt';
export function useResourceHistogram(ganttRef) {
const resourceStore = useGanttDatastore(ganttRef, 'resource');
const { getResourceAssignments } = useResourceAssignments(ganttRef);
const { isWorkTime } = useWorkTime(ganttRef);
const isGroupResource = useCallback((resource) => {
return resourceStore.hasChild(resource.id);
}, [resourceStore]);
const getAllocatedValue = useCallback((tasks, resource) => {
return tasks.reduce((sum, task) => {
const assignments = getResourceAssignments(resource.id, task.id);
return sum + assignments.reduce((acc, a) => acc + Number(a.value), 0);
}, 0);
}, [getResourceAssignments]);
const getCapacity = useCallback((date, resource) => {
if (isGroupResource(resource)) return -1;
return isWorkTime({ date }) ? 8 : 0;
}, [isGroupResource, isWorkTime]);
return { getAllocatedValue, getCapacity, isGroupResource };
}
Direct access to Gantt instance
While hooks handle most advanced needs, you can still access the entire Gantt instance directly via a ref:
import { useRef, useEffect } from 'react';
import ReactGantt, { ReactGanttRef } from '@dhx/react-gantt';
function DirectRefExample({ tasks, links }) {
const ganttRef = useRef<ReactGanttRef>(null);
useEffect(() => {
const gantt = ganttRef.current?.instance;
if (!gantt) return;
gantt.showDate(new Date());
}, []);
return <ReactGantt ref={ganttRef} tasks={tasks} links={links} />;
}
If you alter tasks or links via the direct Gantt instance while also feeding them as React props, keep them in sync. Otherwise, the next React re-render may overwrite your manual changes.