fullcalendar / fullcalendar-react

The official React Component for FullCalendar

Home Page:https://fullcalendar.io/docs/react

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

State changes in FullCalendar callbacks gives warning - Cannot update a component from inside a function body of a different component

meera-coupa opened this issue · comments

Bug Reports

We have created a shared calendar component using the below packages of FullCalendar. We are using this component across multiple applications. If we set the state variable from any callback passed to the FullCalendar, it gives us the warning Cannot update a component from inside a function body of a different component when we integrate a calendar component into another application.

FullCalendar packages -

    "@fullcalendar/core": "^5.11.0",
    "@fullcalendar/daygrid": "^5.11.0",
    "@fullcalendar/interaction": "^5.11.0",
    "@fullcalendar/react": "^5.11.1",
    "@fullcalendar/timegrid": "^5.11.0"

Error screenshot -
image

Details about the calendar component implementation -

import React, { useState, useReducer, useMemo, useCallback, useRef } from "react";
import FullCalendar, { FormatterInput } from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import allLocales from "@fullcalendar/core/locales-all";
import CalendarUtils from "Calendar/CalendarUtils";
import CalendarReducer from "Calendar/CalendarReducer";

type CalendarProps = {
  eventsUrl: string;
  className?: string | Array<string>;
};

// Used while displaying time along with event title
const eventTimeFormat: FormatterInput = {
  hour: "numeric",
  minute: "2-digit",
  omitZeroMinute: true,
  meridiem: "short"
};

// Custom Header title format for Week view
const titleFormat: FormatterInput = {
  year: "numeric",
  month: "long"
};

const Calendar = ({ eventsUrl, className = "" }: CalendarProps) => {
  const [isLoading, setIsLoading] = useState(false);

  const [state, dispatch] = useReducer(
    CalendarReducer,
    {
      initialView: "",
      locale: null,
      timeZone: null,
      eventsLinks: [],
      errorMsg: null
    },
    (initialState) => initialState
  );

  const { initialView, locale, timeZone, eventsLinks } = state;
  /** Fetches events for the calendar */
  const fetchEvents = useCallback(
    (fetchInfo, successCallback, failureCallback) => {

      // Doing setState in tehcallbacks gives this warning, if we remove the warning goes away. 
      setIsLoading(true);
      // calls an ajax API to fetch the events
      // In ajax success response setIsLoading(false)
      setIsLoading(false);
    },
    [eventsLinks]
  );

  const renderLoader = () => {
    return (
      <div className="coupaCalendar__loader s-loadingResults">
        <Spinner size="medium" />
      </div>
    );
  };

  const getFullCalendarProps = useMemo(() => {
    return {
      plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin],
      headerToolbar: {
        left: "prev,next today",
        center: "title",
        right: "dayGridMonth,timeGridWeek,timeGridDay"
      },
      eventTimeFormat,
      views: {
        timeGridWeek: {
          titleFormat
        }
      },
      viewClassNames: "viewContainer s-viewContainer",
      locales: allLocales,
      dayMaxEvents: true,
      initialView: initialView,
      locale: locale,
      timeZone: timeZone
    };
  }, [initialView, locale, timeZone]);

  const onCalendarViewMount = () => {
    renderLoader();
  };

  const loadingCallback = useCallback((isLoading) => {
    renderLoader();
  }, []);

  const handleEventClick = useCallback((e) => {
    return CalendarUtils.handleEventClick(e);
  }, []);

  return (
    <div className="s-fullCalendar">
      <FullCalendar
        {...getFullCalendarProps}
        eventClick={handleEventClick}
        events={fetchEvents}
        loading={loadingCallback}
        viewDidMount={onCalendarViewMount}
      />
  </div>
  );
};

export default React.memo(Calendar);

Any help in resolving this issue is much appreciated.

Please refer to the support page and use Stack Overflow for help. If this is a bug, please supply a runnable, stripped-down demonstration.