Hamza
Hamza

Reputation: 146

Fullcalendar re-fetch events after change in React state

I have this really simple React component:

import { useState } from "react";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import { getCalendarEvents } from "../../utils/frontend/getEvents";
import EventModal from "../CreateEventModal";

const Calendar = ({ calendar: calendarId, eventColor }) => {
  const [isModalVisible, setModalVisibility] = useState(false);

  return (
    <>
      <button onClick={() => setModalVisibility(true)}>Open Modal</button>
      
      <FullCalendar
        plugins={[dayGridPlugin]}
        events={getCalendarEvents(calendarId)}      
      />

      <EventModal open={isModalVisible} onClose={() => setModalVisibility(false)} />
    </>
  );
}

export default Calendar;

Yet, there is a problem. When ever I open the modal, Fullcalendar decides to re-fetch my events. Here the code for getCalendarEvents:

export const getCalendarEvents =
  (calendarId) => (info, successCallback, failureCallback) => {
    fetch(`/list-events?id=${calendarId}&timeMin=${info.start}&timeMax=${info.end}`)
      .then((res) => res.json())
      .then((res) => {
        if (res.success && res.data)
          successCallback(
            res?.data?.map((event) => ({
              id: event.id,
              title: event.summary,
              location: event.location,
              description: event.description,
              start: event.start?.dateTime,
              end: event.end?.dateTime,
            })) || []
          )
        else {
          failureCallback(new Error(res.error || "Something went wrong."));
        }
      })
  };

I believe this is an issue with Fullcalendar itself. However, is there are way to fix this issue from my side?

I am using @fullcalendar/react version 5.10.1.

Upvotes: 0

Views: 2241

Answers (1)

Arťom Pozdnyakov
Arťom Pozdnyakov

Reputation: 617

I believe this happens because every render is processes "events={getCalendarEvents(calendarId)}", which creates new reference to function.

Try something like that:

import { useState, useMemo } from "react";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import { getCalendarEvents } from "../../utils/frontend/getEvents";
import EventModal from "../CreateEventModal";

const Calendar = ({ calendar: calendarId, eventColor }) => {
  const [isModalVisible, setModalVisibility] = useState(false);
  
  const memoizedEventsFn = useMemo(() => {
    return getCalendarEvents(calendarId);
  }, [calendarId]);

  return (
    <>
      <button onClick={() => setModalVisibility(true)}>Open Modal</button>
      
      <FullCalendar
        plugins={[dayGridPlugin]}
        events={memoizedEventsFn}      
      />

      <EventModal open={isModalVisible} onClose={() => setModalVisibility(false)} />
    </>
  );
}

export default Calendar;

I hope it works. If not, it is possible to memoize FullCalendar with memo or useMemo.

Upvotes: 4

Related Questions