A demo of DHTMLX React Scheduler integrated with XState for client-side state management. All event mutations flow through an XState state machine, with undo/redo via history snapshots, view/date state, and event coloring via templates.event_class. Built with React, TypeScript, and Vite.
This demo shows how to use XState — a library for modeling application logic as finite state machines — as the state layer for DHTMLX React Scheduler. All calendar events live inside an XState machine defined in machine.ts. Every mutation (create, update, delete) is an explicit, typed event dispatched to the machine via Scheduler's data.save callback, and every state transition is a named action.
One feature unique to this starter among the Scheduler demos is event coloring: events in the seed data carry a classname property, and the Scheduler's templates.event_class function reads that property to apply CSS classes per event. This is a practical pattern for rendering events with different visual categories (e.g., meeting, deadline, reminder) without custom Scheduler themes.
- Use this demo when your Scheduler integration has complex conditional state logic that is difficult to express as plain store mutations.
- Use this when you need formal guarantees that certain invalid states are impossible by construction, enforced by the machine's transition model.
- Use this as a reference for combining XState history snapshots with Scheduler's
data.savecallback for undo/redo. - Use this when you want a working example of per-event CSS class assignment via
templates.event_class.
git clone https://github.com/DHTMLX/react-scheduler-xstate-starter
cd react-scheduler-xstate-starter
npm install
npm run devOpen http://localhost:5173 in your browser.
Requirements: Node.js 18+, npm.
- Switch between Day, Week, and Month views.
- Click-drag on an empty slot to create a new event — it dispatches a
CREATEevent to the machine. - Drag an existing event to a new time — dispatches an
UPDATEevent. - Delete an event — dispatches a
DELETEevent. - Click Undo and Redo in the toolbar to step through machine history.
- Notice that events in the seed data appear in different colors — these are driven by
classnameon each event andtemplates.event_classin the Scheduler config.
src/
├── components/
│ └── Scheduler.tsx # Scheduler mount, templates (event_class), data.save → machine bridge
├── machine.ts # XState machine: states, events, history, reducers
├── seed/
│ └── data.ts # Seed events with classname, default view and date
└── App.tsx
The machine (machine.ts) owns all state: events, current view, active date, and undo/redo history. Scheduler.tsx subscribes to machine state and passes events, view, and date as props to the Scheduler. When Scheduler fires data.save(...) after a user mutation, Scheduler.tsx dispatches the corresponding typed machine event. The machine transitions, records a history snapshot, and React re-renders.
data.saveto machine event bridge — Scheduler'sdata.save(entity, action, data, id)callback is the single entry point for all mutations.Scheduler.tsxmaps eachactiontype (add,update,delete) to a named XState event, dispatching it to the machine. This makes every possible Scheduler mutation visible and traceable in the machine definition.- Machine history snapshots for undo/redo — undo/redo is implemented by recording machine context snapshots on every mutation transition. Dispatching
UNDOorREDOevents restores the corresponding snapshot, replaying state without custom history stack logic outside the machine. - Event coloring via
templates.event_class— each seed event carries aclassnamefield (e.g."event-type-a"). The Scheduler'stemplates.event_classfunction returns that value, and CSS rules inindex.cssapply the visual style. This is the correct DHTMLX Scheduler pattern for category-based event coloring. - View and date as machine context — active view and current date live inside machine context alongside event data. The toolbar dispatches
SET_VIEWandSET_DATEevents to navigate; these transitions are intentionally excluded from undo history. - Impossible states by construction — the machine's explicit state and transition definitions structurally prevent conflicting concurrent states (such as processing two mutations simultaneously) without defensive runtime guards.
| Feature | Details |
|---|---|
| Event CRUD | Create, update, and delete events via machine events dispatched from data.save |
| Drag-and-drop | Event rescheduling and resize dispatched as UPDATE machine events |
| Views | Day, week, and month |
| Custom toolbar | View switcher, Prev/Next/Today navigation, undo/redo |
| Undo/redo | Machine history snapshot-based, covers event mutations only |
| Event coloring | Per-event CSS classes via classname field and templates.event_class |
| Explicit state model | Named states and typed transitions in machine.ts |
| TypeScript | Full type coverage for machine events, context, and event data |
| Vite | Fast dev server and production build |
This demo is a starter, not a production-ready application. For production use:
- Add persistence — events are in-memory only; page refresh resets to seed data. Add a machine service or
onTransitionhandler that syncs context to an API or database after each mutation. - Extend the machine for your workflow — the demo machine covers CRUD and undo/redo. For real scheduling apps, consider adding states for loading, saving, conflict detection, and optimistic updates. XState's statechart model handles this growth well.
- Add XState DevTools — XState has a dedicated inspector (Stately DevTools) for visualizing and stepping through machine states. Recommended for any non-trivial machine.
- Expand event coloring — the demo uses static
classnamevalues in seed data. In a real app, deriveclassnamefrom event properties (type, owner, priority) and define the corresponding CSS in a shared stylesheet. - Scheduler license — DHTMLX React Scheduler requires a valid commercial license for production use (see License section below).
- DHTMLX React Scheduler product page
- DHTMLX Scheduler product page
- DHTMLX Scheduler documentation
- DHTMLX Scheduler React integration guide
- Scheduler + Zustand starter (simpler store alternative)
- Scheduler + Jotai starter (atomic state alternative)
- Gantt + XState starter (same pattern for Gantt)
- XState documentation
- DHTMLX blog
- Community forum
- Report an issue
The source code in this repository is released under the MIT License.
Commercial License Required for proprietary or commercial applications. Includes access to PRO features, dedicated technical support, and long-term maintenance. Learn more →
Try before you buy A free evaluation of DHTMLX React Gantt is available — no credit card required. Start your evaluation →