React Component

FullCalendar for React, versions 17 - 19, is written in React itself rather than wrapped around the vanilla JS calendar. Everything it draws is a React element, so custom content is ordinary JSX, server-side rendering and StrictMode work, and the whole calendar shows up in React DevTools. Its <FullCalendar> component exactly matches the functionality of FullCalendar’s standard API.

This package is released under an MIT license, the same license the standard version of FullCalendar uses. Useful links:

Installation#

Using a component library? FullCalendar also ships ready-made components for Shadcn and MUI, each with a toolbar in that library’s own widgets and styling that follows its theme. Those guides replace the installation below; everything else on this page still applies.

This guide does not go into depth about initializing a React project. Please consult the aforementioned example/runnable projects for that.

The first step is to install the FullCalendar-related dependencies:

npm install --save @fullcalendar/react temporal-polyfill

The temporal-polyfill package is small and tree-shakable, and can be used as a global polyfill if you explicitly opt-in (more info).

Next, choose one of the stock themes (see them live), along with a color palette. The examples below show a simplified way of importing the color palette (ex: purple.css), but please be aware, there are better ways to integrate with dark mode.

You may then begin to write a parent component that leverages the <FullCalendar> component (DemoApp.tsx):

import FullCalendar from "@fullcalendar/react";
import themePlugin from "@fullcalendar/react/themes/monarch"; // YOUR THEME
import dayGridPlugin from "@fullcalendar/react/daygrid";

// stylesheets
import '@fullcalendar/react/skeleton.css'; // ALWAYS NEED SKELETON
import '@fullcalendar/react/themes/monarch/theme.css'; // YOUR THEME
import '@fullcalendar/react/themes/monarch/palettes/purple.css'; // YOUR THEME'S PALETTE

export default function Calendar() {
  return (
    <FullCalendar
      plugins={[themePlugin, dayGridPlugin]}
      initialView="dayGridMonth"
    />
  );
}

You must initialize your calendar with at least one plugin that provides a view!

Props#

The <FullCalendar> component is equipped with all of FullCalendar’s options! Just pass them in as props. Example:

<FullCalendar
  plugins={[dayGridPlugin]}
  initialView="dayGridMonth"
  weekends={false}
  events={[
    { title: "event 1", date: "2019-04-01" },
    { title: "event 2", date: "2019-04-02" },
  ]}
/>

Props for the <FullCalendar> component are set the same way for both Class and Functional Components.

Options can also be scoped to a single view, or to a type of view, through the views option. See View-Specific Options.

Handlers#

A handler function can be passed into a React component and it will be called when something happens. For example, the dateClick handler is called whenever the user clicks on a date:

export default function Calendar() {
  const handleDateClick = (info) => {
    alert(info.dateStr);
  };

  return (
    <FullCalendar
      plugins={[ /* ... */ ]}
      dateClick={handleDateClick}
    />
  );
}

Modifying Props#

Props are reactive. When a prop’s value changes, the calendar updates to match. There is no need to call a method. This example toggles the weekends prop:

import { useState } from "react";
import FullCalendar from "@fullcalendar/react";
// ...

export default function Calendar() {
  const [weekends, setWeekends] = useState(false);

  return (
    <>
      <button onClick={() => setWeekends(!weekends)}>toggle weekends</button>
      <FullCalendar
        plugins={[ /* ... */ ]}
        weekends={weekends}
      />
    </>
  );
}

Be careful with values written inline, like an events array or a callback. They are new values on every render, so the calendar sees them as changed each time. Define them outside the component, or memoize them with useMemo and useCallback.

Content Injection#

There are many settings throughout the API for injecting custom content, like the eventContent event render hook. When you’re using the React implementation, these settings accept a function that returns JSX. The function receives a single argument, documented alongside each setting. For example, see eventContent’s argument.

export default function Calendar() {
  return (
    <FullCalendar
      plugins={[ /* ... */ ]}
      eventContent={renderEventContent}
    />
  );
}

function renderEventContent(eventInfo) {
  return (
    <>
      <b>{eventInfo.timeText}</b>
      <i>{eventInfo.event.title}</i>
    </>
  );
}

Custom Toolbar Markup#

You can completely customize the markup for the header or footer toolbars:

import FullCalendar, { useCalendarController } from "@fullcalendar/react";
// ...

export default function Calendar() {
  const controller = useCalendarController();
  const buttons = controller.getButtonState();

  return (
    <div>
      <div className='toolbar'>
        <button onClick={() => controller.today()}>{buttons.today.text}</button>
        <div className='toolbar-title'>{controller.view.title}</div>
      </div>
      <FullCalendar
        controller={controller}
        plugins={[ /* ... */ ]}
      />
    </div>
  );
}

More generally, this “controller” technique allows you to use a calendar’s data outside the component itself. Learn about the CalendarController API →

The Shadcn and MUI toolbars are built this way, and are a good reference for a complete one.

Custom Views with Components#

It’s possible to make calendar views that have custom rendering logic. The Custom Views via JS article explains the general concept. When you’re using the React implementation, it’s possible to specify a React component. Example:

import FullCalendar, { sliceEvents } from "@fullcalendar/react";
// ...

function CustomView(props) {
  const segs = sliceEvents(props, true); // allDay=true

  return (
    <>
      <div className="view-title">
        {props.dateProfile.currentRange.start.toUTCString()}
      </div>
      <div className="view-events">{segs.length} events</div>
    </>
  );
}

<FullCalendar
  views={{
    custom: CustomView
  }}
/>

Calendar API#

Hopefully you won’t need to do it often, but sometimes it’s useful to access the underlying Calendar object for raw data and methods.

This is especially useful for controlling the current date. The initialDate prop will set the initial date of the calendar, but to change it after that, you’ll need to rely on the date navigation methods.

To do something like this, you’ll need to get ahold of the component’s ref (short for “reference”). Once you do that, you call the getApi method of the “current” component instance:

import { useRef } from 'react';
import FullCalendar from '@fullcalendar/react'
// ...

export default function Calendar() {
  const calendarRef = useRef(null)

  function goNext() {
    const calendarApi = calendarRef.current.getApi()
    calendarApi.next()
  }

  return (
    <>
      <button onClick={goNext}>Go Next!</button>
      <FullCalendar
        ref={calendarRef}
        plugins={[ /* ... */ ]}
      />
    </>
  )
}

FullCalendar Premium#

How do you use FullCalendar Premium’s plugins with React? They are no different than any other plugin. Just follow the same instructions as you did dayGridPlugin in the above example. You’ll need an additional package however:

npm install --save @fullcalendar/react-scheduler

Then, initialize your calendar. Make sure to include your schedulerLicenseKey:

import FullCalendar from "@fullcalendar/react";
import themePlugin from "@fullcalendar/react/themes/monarch";
import resourceTimelinePlugin from "@fullcalendar/react-scheduler/resource-timeline";

// stylesheets
import '@fullcalendar/react/skeleton.css';
import '@fullcalendar/react/themes/monarch/theme.css';
import '@fullcalendar/react/themes/monarch/palettes/purple.css';

export default function Calendar() {
  return (
    <FullCalendar
      schedulerLicenseKey="XXX"
      plugins={[themePlugin, resourceTimelinePlugin]}
    />
  );
}

TypeScript#

For @fullcalendar/react, nothing special is needed for TypeScript integration. Types are already included.

State Management#

The above mentioned sample project uses a rather simple technique to store event data: it uses the FullCalendar component itself. It’s possible to share this data with other parts of the application, but it’s often useful to have a more sophisticated setup. For example, if you need access to event data when a FullCalendar component isn’t visible.

Please check out the following example projects that demonstrate usage with third-party state-management libraries:

Next.js#

FullCalendar works well with the React framework Next.js. View the example project →

Remix#

FullCalendar works well with the React framework Remix. View the example project →