Google Calendar Events with React
Published: 2021-06-17 13:36:40

This article will cover the topic of viewing a full calendar in your **React** application and integrate with **Google Calendar API** to show events from your account.

First of all, we need a package that provides a full calendar UI. So we will [Full Calendar Package](https://fullcalendar.io/docs). This package is very simple and has many features as localization, different views, theme customizations and more.

First steps would be to install the package in your react app and initialize an **API_KEY** and **CLIENT_ID** in your Google Console to use in Google Calendar APIs.

In your react component, Add the scopes needed by google calendar for user authorization and showing calendar events.

```
const SCOPES =
  "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar";
```
Multiple scopes can be added separated by spaces.

Second, you must add google Api script in your application on component mount like so

```
  const [events, setEvents] = useState(null);

  useEffect(() => {
    const script = document.createElement("script");
    script.async = true;
    script.defer = true;
    script.src = "https://apis.google.com/js/api.js";

    document.body.appendChild(script);

    script.addEventListener("load", () => {
      if (window.gapi) handleClientLoad();
    });
  }, []);
```
This last part ensures that the authorization popup will show only when script is fully loaded and google api is ready.

The `handleClientLoad()` function loads the Auth2 library.
```
  const handleClientLoad = () => {
    window.gapi.load("client:auth2", initClient);
  };
```

Th `initClient()` function will initialize the API client library and set up sign in state listeners.
```
const openSignInPopup = () => {
   window.gapi.auth2.authorize(
              { client_id: CLIENT_ID, scope: SCOPES },
              (res) => {
                if (res) {
                  if (res.access_token)
                    localStorage.setItem("access_token", res.access_token);

                  // Load calendar events after authentication
                  window.gapi.client.load("calendar", "v3", listUpcomingEvents);
                }
              }
            );
}  

const initClient = () => {
    if (!localStorage.getItem("access_token")) {
      openSignInPopup();
    } else {
      // Get events if access token is found without sign in popup
      fetch(
     `https://www.googleapis.com/calendar/v3/calendars/primary/events?key=${API_KEY}&orderBy=startTime&singleEvents=true`,
        {
          headers: {
            Authorization: `Bearer ${localStorage.getItem("access_token")}`,
          },
        }
      )
        .then((res) => {
          // Check if unauthorized status code is return open sign in popup
          if (res.status !== 401) {
            return res.json();
          } else {
            localStorage.removeItem("access_token");

            openSignInPopup();
          }
        })
        .then((data) => {
          if (data?.items) {
            setEvents(formatEvents(data.items));
          }
        });
    }
  };
```
Here we are using two types of methods for fetching events, The first using the logged in `gapi.client` instance and the other using the access_token stored.

When using the `gapi.client`, we are calling a callback function `listUpcomingEvents()` to get the events of the user.
```
const listUpcomingEvents = () => {
    window.gapi.client.calendar.events
      .list({
        // Fetch events from user's primary calendar
        calendarId: "primary",
        showDeleted: true,
        singleEvents: true,
      })
      .then(function (response) {
        let events = response.result.items;

        if (events.length > 0) {
          setEvents(formatEvents(events));
        }
      });
  };
```
Now that we have the events, we need to format them for Full calendar package event object structure.
```
const formatEvents = (list) => {
    return list.map((item) => ({
      title: item.summary,
      start: item.start.dateTime || item.start.date,
      end: item.end.dateTime || item.end.date,
    }));
  };
```
We are only showing title, start date and end dates but there are more options in full calendar docs.

At last, we need to render the Full Calendar component
```
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";

return (
      <FullCalendar
        plugins={[dayGridPlugin]}
        initialView="dayGridMonth"
        events={events}
      />
  );
```
Now we have a full calendar rendering google calendar events.

Hope this was a clear tutorial. Thank you and have a great day.