React Scheduler - Redux Toolkit Tutorial
This tutorial shows how to connect DHTMLX React Scheduler to a Redux Toolkit store. You will keep events and UI state (view/date/config) in Redux, route Scheduler edits through data.save, and add undo/redo with snapshot-based history and a read-only toggle.
The complete source code is available on GitHub.
Prerequisites
- Node.js (LTS recommended)
- React + TypeScript basics
- Redux fundamentals (actions, reducers, store). If you need a refresher, see the Redux docs: https://redux.js.org/
Quick setup - create the project
Create a Vite + React + TS project:
npm create vite@latest scheduler-redux-demo -- --template react-ts
cd scheduler-redux-demo
npm install
Install Redux Toolkit + React Redux:
npm install @reduxjs/toolkit react-redux
Install Material UI (used for the demo toolbar):
npm install @mui/material @mui/icons-material @emotion/react @emotion/styled
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.
Run the dev server:
npm run dev
To make Scheduler occupy the whole page, remove the default styles from src/App.css and add:
#root {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
body {
margin: 0;
}
Configure Redux store
Create src/redux/store.ts. This wires the scheduler reducer into the Redux store:
import { configureStore } from "@reduxjs/toolkit";
import schedulerReducer from "./schedulerSlice";
export const store = configureStore({
reducer: {
scheduler: schedulerReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Define shared types
Create src/redux/types.ts. These types are shared across the slice, actions, and components:
export type SchedulerView = "day" | "week" | "month";
export interface SchedulerEvent {
id: string | number;
start_date: string;
end_date: string;
text: string;
// Scheduler may attach extra fields (e.g. custom props). Keep the demo permissive.
[key: string]: unknown;
}
export type SchedulerConfig = Record<string, unknown>;
export interface SchedulerSnapshot {
events: SchedulerEvent[];
config: SchedulerConfig;
}
SchedulerEventuses an index signature so Scheduler can attach extra fields at runtime.SchedulerSnapshotcaptures the data needed for undo/redo (events + config).