fullcalendar / fullcalendar-react

The official React Component for FullCalendar
https://fullcalendar.io/docs/react
MIT License
2.09k stars 110 forks source link

Nextjs + fullcalendar-react Element is not defined #17

Closed mickelindahl closed 4 years ago

mickelindahl commented 5 years ago

Hi,

Glitch to reproduce the bug https://glitch.com/edit/#!/join/30dcdcf3-668a-449d-aa74-bfe3ff4e5b2c

Using react-fullcalendar 4.1 together with nextjs 8.1 I get ReferenceError: Element is not defined error in node_modules/@fullcalendar/core/main.js

I can fix this by replacing

var matchesMethod = Element.prototype.matches ||
    Element.prototype.matchesSelector ||
    Element.prototype.msMatchesSelector;

with

var matchesMethod=function(s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; };

and

var closestMethod = Element.prototype.closest || function (selector) { // polyfill var el = this; if (!document.documentElement.contains(el)) { return null; } do { if (elementMatches(el, selector)) { return el; } el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; };

with

var closestMethod = function (selector) { // polyfill var el = this; if (!document.documentElement.contains(el)) { return null; } do { if (elementMatches(el, selector)) { return el; } el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; };

Cheers /Mikael

kazuma1989 commented 5 years ago

I faced the same issue except that I'm using fullcalendar-vue with Nuxt.js. My workaround is to use the SPA mode, e.g. in my package.json:

  "scripts": {
-   "dev": "nuxt",
+   "dev": "nuxt --spa",
  },

So Server Side Rendering (SSR) seems the cause of the issue but Next.js doesn't provide SPA mode. This wiki (https://github.com/zeit/next.js/wiki/FAQ) and this library (https://github.com/kadirahq/react-no-ssr) might help.

mickelindahl commented 5 years ago

I tried with react-no-ssr and the problem unfortunately still remained.

SreevishnuAB commented 5 years ago

I can fix this by replacing

var matchesMethod = Element.prototype.matches ||
    Element.prototype.matchesSelector ||
    Element.prototype.msMatchesSelector;

with

var matchesMethod=function(s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; };

and

var closestMethod = Element.prototype.closest || function (selector) { // polyfill var el = this; if (!document.documentElement.contains(el)) { return null; } do { if (elementMatches(el, selector)) { return el; } el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; };

with

var closestMethod = function (selector) { // polyfill var el = this; if (!document.documentElement.contains(el)) { return null; } do { if (elementMatches(el, selector)) { return el; } el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; };

Cheers /Mikael

I've stumbled upon the same issue, but this fix isn't working for me. Any other ideas?

marcosdipaolo commented 5 years ago

Any news about this???

ReferenceError: Element is not defined
    at /home/marcos/Documents/projects/dashboard-react/node_modules/@fullcalendar/core/main.js:107:25
    at elementPropHash.className (/home/marcos/Documents/projects/dashboard-react/node_modules/@fullcalendar/core/main.js:7:68)
    at Object.<anonymous> (/home/marcos/Documents/projects/dashboard-react/node_modules/@fullcalendar/core/main.js:10:2)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.setPrototypeOf.__proto__ (/home/marcos/Documents/projects/dashboard-react/node_modules/@fullcalendar/react/main.umd.js:7:103)
    at Object.<anonymous> (/home/marcos/Documents/projects/dashboard-react/node_modules/@fullcalendar/react/main.umd.js:10:2)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
gyto commented 5 years ago

Having the same issue as @marcosdipaolo with Nextjs, I was ready over other recomendations, and now of them is lazy load and not use SSR. https://nextjs.org/docs#with-no-ssr. I will try to use in my project in day to see if it will actually trigger without SSR

marcosdipaolo commented 5 years ago

Having the same issue as @marcosdipaolo with Nextjs, I was ready over other recomendations, and now of them is lazy load and not use SSR. https://nextjs.org/docs#with-no-ssr. I will try to use in my project in day to see if it will actually trigger without SSR

did you try that??? another solution?

gyto commented 5 years ago

@marcosdipaolo yep it works fine, by disabling SSR on the component. Thank you @marcosdipaolo for the reminder!

marcosdipaolo commented 5 years ago

@marcosdipaolo yep it works fine, by disabling SSR on the component. Thank you @marcosdipaolo for the reminder!

Dou you have a code example?

gyto commented 5 years ago

@marcosdipaolo Simple as that

// @flow
import React from 'react'
import dynamic from 'next/dynamic'
import Page from '../../components/Page'

const DynamicCalendar = dynamic(
    () => import('../../components/Admin/Calendar'),
    {
        ssr: false, <------- just set this part to false
    }
);

export default () => (
    <Page title='Calendar | Hair Line Salon'>
        <DynamicCalendar/>
    </Page>
)
// @flow
import * as React from 'react';
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';

class EventCalendar extends React.Component<Props, State> {
    calendarComponentRef: {
        current: HTMLDivElement | null,
    };

    constructor(props: Props) {
        super(props);

        this.state = {
            events: [],
            calendarEvents: [],
            calendarReminders: [],
        };
        this.calendarComponentRef = React.createRef();
    }

    render() {
        const { calendarEvents, calendarReminders } = this.state;
        return (
            <>
                    <FullCalendar
                        ref={this.calendarComponentRef}
                        header={{
                            left: 'prev,next today',
                            center: 'title',
                            right: 'timeGridWeek,timeGridDay,listWeek',
                        }}
                        height='auto'
                        defaultView='timeGridDay'
                        plugins={[
                            dayGridPlugin,
                            timeGridPlugin,
                        ]}
                        events={[
                            ...calendarEvents,
                            ...calendarReminders,
                        ]}
                        allDaySlot={false}
                    />
            </>
        );
    }
}

export default EventCalendar;
alfredrumss commented 5 years ago

facing the same

ghost commented 4 years ago

same. Can you put Mikael's solution into the repo?.. it works. By the way I'm not using next.js it's just React.

remjx commented 4 years ago

Does anybody know what the actual issue is here, why the calendar can't be server rendered?

kishankanugula commented 4 years ago

Any workaround for just using React?

mehlleniumfalke commented 4 years ago

Same problem here. If i disable SSR it will work in development mode. But if i try to build i get the "Element is not defined" error.

danielblignaut commented 4 years ago

it seems to be a SSR polyfill issue for window.Element... we managed to get rid of the issue on the server render by adding the following code before the library is loaded or at the start up of the app. Unsure of the full effects of the below however.

if(typeof Element === 'undefined') {
    global.Element = function() {

    }
}
ehubbell commented 4 years ago

We use a full-calendar-wrapper component that wraps the @fullcalendar library and then use the loadable/component library to handle our imports for SSR like so:

import React, { Component } from 'react';
import loadable from '@loadable/component';

const FullCalendar = loadable(() => import('@fullcalendar/react'), { ssr: false });
const DayGrid = loadable(() => import('@fullcalendar/daygrid'));
const Interactions = loadable(() => import('@fullcalendar/interaction'));

class FullCalendarWrapper extends Component {
  // Render
  render() {
    const { data } = this.props;
    const { type, showForm, css } = this.state;

    return (
      <div className={'fc-block' + ' ' + type}>
         {typeof window !== 'undefined' && (
       <FullCalendar 
              ref={this.calendarRef}
              defaultView='dayGridMonth'
              header={{}}
              height='parent'
              plugins={[ DayGrid, Interactions ]}
              dateClick={args => this.clickedDate(args)}
              eventClick={args => this.clickedEvent(args)}
              events={data}
             />
          )}
      </div>
    )
  }
}

export default FullCalendarWrapper;

Unfortunately, the code above doesn't work in some situations as the dayGrid and Interactions components can't be loaded via loadable(). I had to convert those back to normal import statements and then wrap the whole <FullCalendarWrapper/> component in a typeof window !== 'undefined' statement so those imports don't run unless the window is available.

kishankanugula commented 4 years ago

@ehubbell I ended up using the loadable/component library.

acerix commented 4 years ago

Sorry for the delay in responding to your issue, I have just began triaging on this repo. Please see this post about the state of the repo (https://github.com/fullcalendar/fullcalendar-react/issues/66) for more info.

This incompatibility with SSR is not specific to React, the same issue was reported in the main repo: https://github.com/fullcalendar/fullcalendar/issues/4784 ↑ Please visit the above issue, give a 👍 to vote (?), press the 🔈Subscribe button to receive updates.