Quick Start with React Scheduler
This tutorial covers the React wrapper included in the Commercial, Enterprise, and Ultimate editions of DHTMLX Scheduler. If you are using the Individual or GPL edition, follow the alternative guide: How to Start with React.
The React Scheduler component is the official wrapper for DHTMLX Scheduler. This guide walks you through creating a small React application and rendering a basic Scheduler using the trial package.
If you're new to React, start with the official React documentation. Check a complete working project that follows this tutorial on GitHub.
Version requirements
- React 18 or newer
Creating a new React project
To create a React project and go to the project directory, run the following commands:
npm create vite@latest react-scheduler-quick-start -- --template react-ts
cd react-scheduler-quick-start
Installing React Scheduler
Install React Scheduler as described in the React Scheduler installation guide.
In this tutorial we use the evaluation package:
npm install @dhtmlx/trial-react-scheduler
or
yarn add @dhtmlx/trial-react-scheduler
If you already use the Professional package, replace @dhtmlx/trial-react-scheduler with @dhx/react-scheduler in the commands and imports.
Adding demo data
We'll use static data for this example. Create a file named src/demoData.ts:
import type { Event } from '@dhtmlx/trial-react-scheduler';
export const events: Event[] = [
{
id: 1,
classname: 'blue',
start_date: new Date('2025-12-08T02:00:00Z'),
end_date: new Date('2025-12-08T10:20:00Z'),
text: 'Product Strategy Hike',
},
{
id: 2,
classname: 'blue',
start_date: new Date('2025-12-08T12:00:00Z'),
end_date: new Date('2025-12-08T16:00:00Z'),
text: 'Agile Meditation and Release',
},
{
id: 3,
classname: 'violet',
start_date: new Date('2025-12-09T06:00:00Z'),
end_date: new Date('2025-12-09T11:00:00Z'),
text: 'Tranquil Tea Time',
},
// ....
];
Creating a Scheduler component
To add a Scheduler component, create an src/components/Scheduler/Scheduler.tsx file with the following content:
import { useMemo, useRef } from 'react';
import ReactScheduler, {
type ReactSchedulerRef,
type Event,
type SchedulerTemplates,
type SchedulerConfig,
} from '@dhtmlx/trial-react-scheduler';
import '@dhtmlx/trial-react-scheduler/dist/react-scheduler.css';
import './styles.css';
export interface ReactSchedulerProps {
events: Event[];
activeView?: string;
activeDate?: Date;
}
export default function Scheduler({
events,
activeView = 'week',
activeDate = new Date('2025-12-08T00:00:00Z'),
}: ReactSchedulerProps) {
const schedulerRef = useRef<ReactSchedulerRef>(null);
const templates: SchedulerTemplates = useMemo(
() => ({
event_class: (start: Date, end: Date, event: Event) => {
return event.classname || '';
},
}),
[]
);
const config: SchedulerConfig = useMemo(() => {
return {
first_hour: 6,
last_hour: 22,
hour_size_px: 60,
};
}, []);
return (
<ReactScheduler
ref={schedulerRef}
events={events}
view={activeView}
date={activeDate}
templates={templates}
config={config}
data={{
save: (entity: string, action: string, data: Event, id: string | number) => {
console.log(`${entity} - ${action} - ${id}`, data);
},
}}
/>
);
}
Finally, the CSS classes (.violet, .green, .yellow) are applied through the event_class template to customize the visual appearance of the events:
.violet {
--dhx-scheduler-event-background: linear-gradient(180deg, #d071ef 0%, #ee71d5 100%);
}
.green {
--dhx-scheduler-event-background: linear-gradient(180deg, #12d979 0%, #1ecdeb 100%);
}
.yellow {
--dhx-scheduler-event-background: linear-gradient(180deg, #ffb725 0%, #ffbb25 31.25%, #faea27 100%);
}
Rendering Scheduler in the App
To display Scheduler, replace the code of src/App.tsx with the following one:
import './App.css';
import Scheduler from './components/Scheduler/Scheduler';
import { events } from './demoData';
function App() {
return (
<div style={{ width: '100vw', height: '100vh' }}>
<Scheduler events={events} />
</div>
);
}
export default App;
After that, run the app using the command below:
npm run dev
At this point, you have a fully working React + DHTMLX Scheduler application.
This setup represents the minimum configuration needed to:
- render a Scheduler
- display events
- apply a basic scale configuration
- attach the Scheduler instance via a React ref
- receive events through the
data.savecallback
This is the same minimal example used in the GitHub demo project.
From here, you can continue by adding more advanced features:
- syncing data with React state
- loading/saving data from your backend
- adding templates and custom renderers
- adding filtering
- replacing the Lightbox with a custom component
The next sections introduce these capabilities one by one.
Using React state as the source of truth
(recommended for most React apps)
In real applications events usually come from the React state.
Below is a complete example where Scheduler sends changes back to React via the data.save callback.
import { useState } from 'react';
import ReactScheduler, { Event } from '@dhtmlx/trial-react-scheduler';
import '@dhtmlx/trial-react-scheduler/dist/react-scheduler.css';
import { events as initialEvents } from './demoData';
export default function App() {
const [events, setEvents] = useState<Event[]>(initialEvents);
const data = {
save: (entity, action, item, id) => {
if (entity === 'event') {
if (action === 'create') setEvents((prev) => [...prev, item]);
if (action === 'update') setEvents((prev) => prev.map((x) => (x.id === id ? item : x)));
if (action === 'delete') setEvents((prev) => prev.filter((x) => x.id !== id));
}
},
};
return (
<div style={{ height: '100vh', width: '100vw' }}>
<ReactScheduler
events={events}
data={data}
// ...other props
/>
</div>
);
}
Why choose this mode
- React always sees the same data as the Scheduler UI
- Works perfectly with Redux / Zustand / Jotai / MobX
- Easy to sync with backend APIs
Alternative Mode: Scheduler as the source of truth
(useful for very large datasets)
In this mode React does not own events.
<ReactScheduler
data={{
load: '/api/data', // scheduler loads initial events from here
save: '/api/data', // scheduler sends updates back here
}}
/>
When to prefer this mode
- Tens of thousands of events
- Frequent user interactions and updates
- You want minimal React rendering overhead
Using Templates
(return React elements from template functions)
Templates allow customizing almost every part of the scheduler.
import ReactScheduler, { SchedulerTemplates } from '@dhtmlx/trial-react-scheduler';
import { useMemo } from 'react';
import EventTextBox from './components/EventTextBox';
const templates: SchedulerTemplates = useMemo(
() => ({
event_class: (start, end, event) => {
return 'templates-' + event.classname || '';
},
event_text: (start, end, event) => {
return <EventTextBox event={event} />;
},
}),
[]
);
<ReactScheduler templates={templates} />;
More details
See the full section here: React Scheduler Templates Documentation.
GitHub demo repository
A complete working project that follows this tutorial is provided on GitHub.
Next steps
- Study all the available React Scheduler props
- Explore advanced Scheduler features in the Guides