---
title: "React Event calendar Double Booking Prevention Example | Mobiscroll"
component: "Event calendar"
framework: "React"
library_version: "6.2.0"
url: "https://demo.mobiscroll.com/react/eventcalendar/prevent-double-booking-events"
---

# Double Booking Prevention - React Event calendar demo

Prevent overlapping events in a React event calendar — block double bookings per event or across all events with in-calendar conflict alerts. For React and Next.js.

- [Live demo](https://demo.mobiscroll.com/react/eventcalendar/prevent-double-booking-events)
- [View React JS code on GitHub](https://github.com/acidb/mobiscroll-demos-react/tree/main/src/demos/eventcalendar/calendar-view/prevent-double-booking-events)
- [View React TS code on GitHub](https://github.com/acidb/mobiscroll-demos-react-ts/tree/main/src/demos/eventcalendar/calendar-view/prevent-double-booking-events)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/eventcalendar/prevent-double-booking-events.md), [jQuery](https://demo.mobiscroll.com/jquery/eventcalendar/prevent-double-booking-events.md), [Angular](https://demo.mobiscroll.com/angular/eventcalendar/prevent-double-booking-events.md), [Vue](https://demo.mobiscroll.com/vue/eventcalendar/prevent-double-booking-events.md)

## Description

Sometimes it is necessary to guarantee that events don't overlap - eg. when scheduling workorders, interacting with a work calendar. You can reject the updates or additions and let the user know about it.

The event overlap can be turned on/off on an event basis or globally on the instance.

- On an [event](https://demo.mobiscroll.com/react/eventcalendar/event-data-structure) basis - by setting the `overlap` property to `false` the specified event cannot overlap.
- Globally on the instance - by setting [`eventOverlap`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-eventOverlap) option to `false` overlap is disbled globally.

If set to `false`, the [event](https://demo.mobiscroll.com/react/eventcalendar/event-data-structure) settings have precedence over the global calendar [`eventOverlap`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-eventOverlap) option.

Give feedback to the user - optionally, a toast can be displayed to explain why an event cannot be dropped, moved or created. For this we can use the `onEventCreateFailed` and `onEventUpdateFailed` lifecycle events.

**Looking to implement time off or block out ranges?** [Learn how to add lunch breaks, working hours and disable weekends →](https://demo.mobiscroll.com/react/scheduler/time-off-blocked-ranges)

## What this demo shows

- A desktop month view event calendar where events can be allowed or prevented from overlapping, either per event or for the whole calendar.
- **Calendar header** The header shows the current month and year on the left, and blue month navigation arrows with a `Today` button between them on the right.
- **Month grid** Day cells display events, each label has a blue line on the left, the background of the event have the same color, the event title, and an `end` value that shows the event end time.
- **Event interaction** Hovering over or selecting an event label highlights it and shows resize handles on both sides, indicating that the event can be resized by clicking and dragging.
- **Per-event overlap prevention** Events titled `Event 2 (no event overlap)` and `Event 4 (no event overlap)` block new event creation in their occupied day cells.
- **Creation feedback** When a user tries to create an overlapping event in a restricted cell, a `Make sure not to overbook` toast appears at the bottom center of the calendar.
- **Global overlap control** A switch under this title: `Control the interaction globally (all events)` lets users enable `Events cannot overlap eventOverlap=false` to prevent overlaps across all events.
- **Day cell states** Hovering a day cell highlights the day number with a gray background, while clicking the empty part of the cell selects the day and highlights the day number with a blue background.
- **Event creation** Double-clicking or clicking and dragging on the empty area of a day cell creates a new event.

## Best for

- **Work orders and field service** Preventing technicians, crews, or jobs from being booked into the same time slot when overlap is not allowed.
- **Availability-sensitive booking** Handling internal planning or booking flows where double booking needs to be blocked for some event types or for the whole calendar.
- **Interactive planning UIs** Showing users immediately when an event cannot be created because it would overbook the selected date or time range.

## Tutorial

### Control the interaction globally (all events)

- [ ] Events cannot overlap `eventOverlap=false`

```jsx
// relevant events
const myData = [{
    start: '2026-11-05T00:00',
    end: '2026-11-07T00:00',
    title: 'Event 2 (no event overlap)',
    overlap: false
}, {
    start: '2026-11-10T00:00',
    end: '2026-11-12T00:00',
    title: 'Event 4 (no event overlap)',
    overlap: false
}];

<Eventcalendar
    view={{
        calendar: { type: 'month', labels: "all" }
    }}
    data={myData}
    dragToMove={true}
    dragToResize={true}
    eventOverlap={true}
    exclusiveEndDates ={true} 
    clickToCreate={true}
    dragToCreate={true}
/>
```

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-themeVariant) - option
- [`labels`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-labels) - option
- [`data`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-data) - option
- [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) - option
- [`dragToCreate`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-dragToCreate) - option
- [`dragToMove`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-dragToMove) - option
- [`dragToResize`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-dragToResize) - option
- [`clickToCreate`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-clickToCreate) - option
- [`eventOverlap`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-eventOverlap) - option
- [`onEventUpdateFailed`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onEventUpdateFailed) - event
- [`onEventCreateFailed`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onEventCreateFailed) - event
- [`exclusiveEndDates`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-exclusiveEndDates) - option
- [`onClose`](https://mobiscroll.com/docs/react/notifications/toast#event-onClose) - event

## Code

### JSX

```jsx
import { Eventcalendar, setOptions, Toast } from '@mobiscroll/react';
import { useCallback, useMemo, useState } from 'react';

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();

function App() {
  const [isToastOpen, setToastOpen] = useState(false);

  const myEvents = useMemo(
    () => [
      {
        start: new Date(y, m, d - 3),
        end: new Date(y, m, d - 1),
        title: 'Event 1',
      },
      {
        start: new Date(y, m, d),
        end: new Date(y, m, d + 2),
        title: 'Event 2 (no event overlap)',
        overlap: false,
      },
      {
        start: new Date(y, m, d + 3),
        end: new Date(y, m, d + 5),
        title: 'Event 3',
      },
      {
        start: new Date(y, m, d + 5),
        end: new Date(y, m, d + 7),
        title: 'Event 4 (no event overlap)',
        overlap: false,
      },
    ],
    [],
  );

  const myView = useMemo(() => ({ calendar: { type: 'month', labels: 'all' } }), []);

  const handleEventFailed = useCallback(() => {
    setToastOpen(true);
  }, []);

  const handleToastClose = useCallback(() => {
    setToastOpen(false);
  }, []);

  return (
    <>
      <Eventcalendar
        data={myEvents}
        view={myView}
        dragToCreate={true}
        dragToMove={true}
        dragToResize={true}
        clickToCreate={true}
        eventOverlap={false}
        onEventUpdateFailed={handleEventFailed}
        onEventCreateFailed={handleEventFailed}
        exclusiveEndDates={true}
      />
      <Toast message="Make sure not to double book" isOpen={isToastOpen} onClose={handleToastClose} />
    </>
  );
}

export default App;
```

### TSX

```tsx
import { Eventcalendar, MbscCalendarEvent, MbscEventcalendarView, setOptions, Toast } from '@mobiscroll/react';
import { FC, useCallback, useMemo, useState } from 'react';

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();

const App: FC = () => {
  const [isToastOpen, setToastOpen] = useState<boolean>(false);

  const myEvents = useMemo<MbscCalendarEvent[]>(
    () => [
      {
        start: new Date(y, m, d - 3),
        end: new Date(y, m, d - 1),
        title: 'Event 1',
      },
      {
        start: new Date(y, m, d),
        end: new Date(y, m, d + 2),
        title: 'Event 2 (no event overlap)',
        overlap: false,
      },
      {
        start: new Date(y, m, d + 3),
        end: new Date(y, m, d + 5),
        title: 'Event 3',
      },
      {
        start: new Date(y, m, d + 5),
        end: new Date(y, m, d + 7),
        title: 'Event 4 (no event overlap)',
        overlap: false,
      },
    ],
    [],
  );

  const myView = useMemo<MbscEventcalendarView>(
    () => ({
      calendar: { type: 'month', labels: 'all' },
    }),
    [],
  );

  const handleEventFailed = useCallback(() => {
    setToastOpen(true);
  }, []);

  const handleCloseToast = useCallback(() => {
    setToastOpen(false);
  }, []);

  return (
    <div>
      <Eventcalendar
        data={myEvents}
        view={myView}
        dragToCreate={true}
        dragToMove={true}
        dragToResize={true}
        clickToCreate={true}
        eventOverlap={false}
        exclusiveEndDates={true}
        onEventUpdateFailed={handleEventFailed}
        onEventCreateFailed={handleEventFailed}
      />
      <Toast message="Make sure not to double book" isOpen={isToastOpen} onClose={handleCloseToast} />
    </div>
  );
};
export default App;
```

## Implementation notes

- Set `view: { calendar: { type: 'month', labels: 'all' } }`. Enable `clickToCreate: true`, `dragToCreate: true`, `dragToMove: true`, and `dragToResize: true` so users can create and edit events interactively. Set `exclusiveEndDates: true` so that events touching at a boundary are not treated as overlapping.
- Set `eventOverlap: false` on the calendar to prevent any two events from overlapping across the whole instance. To prevent a specific event from overlapping regardless of the global setting, set `overlap: false` directly on that event data object.
- `onEventCreateFailed` and `onEventUpdateFailed` (Vue: `@event-create-failed`, `@event-update-failed`) fire whenever Mobiscroll blocks a creation or move due to an overlap violation.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-react.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config react
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config react --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/react/getting-started/installation

## Related demos

- Previous: [Blocked Days and Date Ranges](https://demo.mobiscroll.com/react/eventcalendar/blocked-days-ranges.md) - Disable weekends and date ranges in a React event calendar — block dates and drag-and-drop, and choose between strict or permissive validation modes.
- Next: [Drag-and-Drop Task Presets](https://demo.mobiscroll.com/react/eventcalendar/external-event-presets.md) - Drag preset task templates from an external list onto a React event calendar — a popup form captures task details and technician at drop time.
