Skip to content

The ref handle

React only. A ref on <Gantt> is the chart’s handle: scrollToTask, setViewMode, select, updateTask, undo, edit.begin and the other methods of the vanilla chart (without destroy, which React does), for code that does not run while rendering, such as a click handler. The buttons above the chart call them, and the first line under the buttons says what each call returned.

Terminal window
pnpm add @ganttlane/react react react-dom
React onlyView on GitHub
data.ts
import type { Link, Task } from '@ganttlane/core';
// 2026-03-02 is a Monday. Nine tasks over seven weeks: more than the chart shows at once, on both
// axes, so that the scroll buttons have somewhere to go.
export const tasks: Task[] = [
{ id: 'research', name: 'Research', start: '2026-03-02', end: '2026-03-06', progress: 100 },
{ id: 'design', name: 'Design', start: '2026-03-09', end: '2026-03-13', progress: 60 },
{ id: 'build', name: 'Build', start: '2026-03-16', end: '2026-03-27', progress: 30 },
{ id: 'docs', name: 'Docs', start: '2026-03-23', duration: 5 },
{ id: 'review', name: 'Review', start: '2026-03-30', end: '2026-04-03' },
{ id: 'qa', name: 'QA', start: '2026-04-06', end: '2026-04-10' },
{ id: 'marketing', name: 'Marketing', start: '2026-04-06', end: '2026-04-17' },
{ id: 'support', name: 'Support', start: '2026-04-13', end: '2026-04-17' },
{ id: 'launch', name: 'Launch', type: 'milestone', start: '2026-04-20' },
];
export const links: Link[] = [
{ source: 'research', target: 'design' },
{ source: 'design', target: 'build' },
{ source: 'build', target: 'review' },
{ source: 'docs', target: 'review' },
{ source: 'review', target: 'qa' },
{ source: 'qa', target: 'support' },
{ source: 'support', target: 'launch' },
{ source: 'marketing', target: 'launch' },
];

Files

  • data.ts: nine tasks over seven weeks and the links between them.
  • options.ts: the view mode, history and the first scroll.
  • react.tsx: the ref, a table of buttons (each is one call on the handle), a listener added with on.

Options

Option Value What it does
ref useRef<GanttHandle>(null) The handle: the methods of the chart
defaultViewMode 'day' The scale of the timeline; the chart owns it, so setViewMode sticks
history true Records every change, so that undo() and redo() have an entry to step
scroll.initial 'first-task' Opens on the plan; the default, 'today', is far from these dates
defaultTasks, defaultLinks the tasks and links Where the chart starts with its data; it owns it, and updateTask changes it

What to try

  • View. Week and Month change the scale and keep the date at the centre in place. Go to Launch scrolls on both axes (the bar is below and to the right of the first screen).
  • Select. Select Design selects the task in code, and its bar is drawn selected. A click on an arrow selects a link instead (a click on a bar does not select a task). The second line under the buttons is a listener added with on('selectionChange', …): it hears both, as (tasks, link).
  • Change. Design +10% is updateTask with a progress. Build +1 week is updateTask with a start: Build keeps its length and the tasks that follow it move along the links, so the status line counts more than one changed task. Both are recorded: Undo and Redo step through them, and say empty when there is nothing to step to.
  • Edit session. Edit opens a session (edit.begin()). Drag some bars, then Cancel puts every bar back, or Save keeps them and counts the net changes.

Notes

  • The handle is for commands, not for rendering. It is the same object for the life of the component and calling a method does not render anything. To show a part of the chart’s state in your UI (whether undo() can step, which tasks are selected, the visible dates) read it with useGanttState: see Hooks.
  • ref.current is null before the chart is committed and after the component unmounts (and while a hidden <Activity> has the chart), so write chart.current?.…. It is set before the layout effects of the parent run, so an effect may use it at once, as the on call here does.
  • Listeners. on(name, handler) takes the events of the on<Event> props (selectionChange for onSelectionChange) and returns the function that removes the listener, which is what an effect returns. Use the props for what belongs to a render, and on for a log or an analytics call.
  • Controlled props win. viewMode, tasks, links, expandedKeys and selectedKeys have a prop that makes the group yours. Then a method of the handle (setViewMode, select, collapse, …) calls your handler and the chart goes back to what your state says, unless the handler changes your state. Here the chart owns them (defaultViewMode, defaultTasks), so the methods stick. The other way is shown in Controlled state.
  • Results are values. updateTask resolves to committed (with the changeSet), unchanged, rejected, busy or cancelled; undo() and redo() to undone / redone, empty, stale, busy or cancelled; edit.begin(), commit() and rollback() to a status too (begun, already-open, committed, rolled-back, no-session, …). Nothing throws for a refused change.
  • TData flows through the handle: useRef<GanttHandle<Meta>>(null) for tasks with a typed data, as in A release plan.