How to use FullCalendar in Next.js

In this tutorial, we would be learning on how to use FullCalendar in Next.js.

You might have been able to come here because you have encountered an error Element is not defined when you are trying to use FullCalendar in Next.js project.

Before we proceed with the solution, I will just point out the cause of that error.

Next.js renders the page on the server side. Since it was on the server side, window is not available as it is only available on the client side. If the window is not available, then the element is also not available.

Now that we understand the problem, let’s proceed with the solution.

Step 1: Initialize a Next.js project

Let’s start with initializing our Next.js project by running the following commands in the terminal.

mkdir nextjs-fullcalendar
cd nextjs-fullcalendar
touch package.json

In the package.json that we have created, paste the following.

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

In the terminal, install Next.js by running the following command.

npm install --save next react react-dom

Now, let’s create our landing page. Run the following commands in the terminal.

mkdir pages
touch pages/index.js

In the file pages/index.js, paste the following.

export default function Home() {
  return <div>Welcome to Next.js!</div>
}

We just created a Home component that simply shows a short message on our landing page.

Step 2: Setup Next.js CSS support

Since FullCalendar has custom CSS, we must setup our Next.js project to support CSS.

In the terminal run the following.

npm install --save node-sass @zeit/next-sass @zeit/next-css
touch next.config.js

In the file next.config.js, paste the following.

const withSass = require('@zeit/next-sass')
module.exports = withSass()

Step 3: Install FullCalendar

Now, let’s install FullCalendar to our project. Run the following command in the terminal.

npm install --save @fullcalendar/core @fullcalendar/react @fullcalendar/daygrid @fullcalendar/timegrid

Let’s create an SCSS file for the FullCalendar CSS by running the following commands in the terminal.

mkdir styles
touch styles/calendar.scss

In the file styles/calendar.scss, paste the following.

@import '[email protected]/core/main.css';
@import '[email protected]/daygrid/main.css';
@import '[email protected]/timegrid/main.css';

Step 4: Create your own no SSR FullCalendar component

Let’s start by creating a directory for our components. Run the following commands in the terminal.

mkdir components
touch components/fullcalendar.js

In the file components/fullcalendar.js, paste the following.

import dynamic from 'next/dynamic'
import { useEffect, useState } from 'react'

import '../styles/calendar.scss'

let CalendarComponent



export default function FullCalendar(props) {

  const [calendarLoaded, setCalendarLoaded] = useState(false)

  useEffect(() => {
    CalendarComponent = dynamic({
      modules: () => ({
        calendar: import('@fullcalendar/react'),
        dayGridPlugin: import('@fullcalendar/daygrid'),
        timeGridPlugin: import('@fullcalendar/timegrid')
      }),
      render: (props, { calendar: Calendar, ...plugins }) => (
        <Calendar {...props} plugins={Object.values(plugins)} ref={props.myRef} />
      ),
      ssr: false
    })

    setCalendarLoaded(true)
  })

  let showCalendar = (props) => {
    if ( !calendarLoaded ) return <div>Loading ...</div>

    return (
      <CalendarComponent {...props} />
    )
  }

  return (
    <div>
      {showCalendar(props)}
    </div>
  )

}

The problem that we have is that Next.js renders our page in the server. In the docs, there is a way to dynamically import packages with no ssr.

We simply imported the FullCalendar component dynamically using Next.js’s dynamic function with an attribute ssr: false to make sure that it is not rendered on the server.

We also imported it in React’s useEffect() hook just to be sure that the window is already defined.

Step 5: Use our own FullCalendar component

In the file pages/index.js, paste the following.

import FullCalendar from '../components/fullcalendar'



export default function Home() {
  return (
    <div>
      <FullCalendar defaultView='dayGridMonth' />
      <FullCalendar defaultView='timeGridWeek' />
    </div>
  )
}

Now if you run npm run dev in the terminal and navigate to http://localhost:3000 in your browser, you should be able to see the two (2) calendars, one in month view and one in week view rendered properly without any errors.

TL;DR

Install FullCalendar using the following command.

npm install --save @fullcalendar/core @fullcalendar/react @fullcalendar/daygrid @fullcalendar/timegrid

Import the CSS in your styles.

@import '[email protected]/core/main.css';
@import '[email protected]/daygrid/main.css';
@import '[email protected]/timegrid/main.css';

Dynamically import FullCalendar with no SSR and use the component in your project.

import dynamic from 'next/dynamic'
import { useEffect, useState } from 'react'

import '../styles/calendar.scss'

let FullCalendar



export default function Home(props) {

  const [calendarLoaded, setCalendarLoaded] = useState(false)

  useEffect(() => {
    FullCalendar = dynamic({
      modules: () => ({
        calendar: import('@fullcalendar/react'),
        dayGridPlugin: import('@fullcalendar/daygrid'),
        timeGridPlugin: import('@fullcalendar/timegrid')
      }),
      render: (props, { calendar: Calendar, ...plugins }) => (
        <Calendar {...props} plugins={Object.values(plugins)} ref={props.myRef} />
      ),
      ssr: false
    })

    setCalendarLoaded(true)
  })

  let showCalendar = (props) => {
    if ( !calendarLoaded ) return <div>Loading ...</div>

    return (
      <FullCalendar {...props} />
    )
  }

  return (
    <div>
      {showCalendar(props)}
    </div>
  )

}

That’s it, we have learned on how to use FullCalendar in Next.js project.

Reference: Using fullcalendar with Next.js