How to Integrate Google Calendar API with React JS?

Viewed 19589

I am trying to implement this vanilla js example of google calendar api in a react js app. The vanilla JS example works just fine in my local machine. But am getting lot of troubles when implementing the same in react. Please check my code below:

class App extends React.Component{
  constructor(props) {
    super(props);
    var CLIENT_ID = '992549188018-3prg54pp18je3e3qhgcttgl11491c4dm.apps.googleusercontent.com';
    var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
    var SCOPES = "https://www.googleapis.com/auth/calendar";
    this.state = {
      showAuthButton: false,
      showSignOutButton: false
    };
    this.initClient = this.initClient.bind(this);
    this.updateSigninStatus = this.updateSigninStatus.bind(this);
  }
  handleAuthClick(){
    gapi.auth2.getAuthInstance().signIn();
  }
  handleSignoutClick(){
    gapi.auth2.getAuthInstance().signOut();
  }
  handleClientLoad() {
    gapi.load('client:auth2', this.initClient);
  }
  initClient(DISCOVERY_DOCS, CLIENT_ID, SCOPES) {
    gapi.client.init({
      discoveryDocs: DISCOVERY_DOCS,
      clientId: CLIENT_ID,
      scope: SCOPES
    }).then(function () {
      console.log(window.gapi);
      // Listen for sign-in state changes.
      window.gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

      // Handle the initial sign-in state.
      updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
      authorizeButton.onclick = handleAuthClick;
      signoutButton.onclick = handleSignoutClick;
    });
  }
  updateSigninStatus(isSignedIn) {
    if (isSignedIn) {
      this.setState({
        showAuthButton: false,
        showSignOutButton: true
      })
      //listUpcomingEvents();
      //insertNewEvent();
    } else {
      this.setState({
        showAuthButton: true,
        showSignOutButton: false
      })
    }
  }
  componentDidMount(){
    this.handleClientLoad();
  }
  render(){
    let authButton = <button id="authorize-button" onClick={this.handleAuthClick.bind(this)}>Authorize</button>
    let signOutButton = <button id="signout-button" onClick={this.handleSignoutClick.bind(this)}>Sign Out</button>
    return(
      <div className="container">
        {this.state.showAuthButton ? authButton : null}
        {this.state.showSignOutButton ? signOutButton : null}
      </div>
    )
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

Am getting this error as of now:

Uncaught TypeError: Cannot read property 'isSignedIn' of null

Please guide me to move further...

3 Answers

I'm using a HOC to load the google API:

import React from "react";
import { API_KEY } from "./constants";
import LoadingIndicator from "./common/LoadingIndicator";

export default function withGoogleApps(WrappedComponent) {
  class ComponentWithGoogleAPI extends React.Component {
    state = { gapiReady: false };

    componentDidMount() {
      this.loadGoogleAPI();
    }

    loadGoogleAPI() {
      const script = document.createElement("script");
      script.src = "https://apis.google.com/js/client.js";

      script.onload = () => {
        window.gapi.load("client", () => {
          window.gapi.client.setApiKey(API_KEY);
          window.gapi.client.load("calendar", "v3", () => {
            this.setState({ gapiReady: true });
          });
        });
      };

      document.body.appendChild(script);
    }

    render() {
      const { gapiReady } = this.state;
      if (gapiReady) return <WrappedComponent />;
      return <LoadingIndicator />;
    }
  }
  return ComponentWithGoogleAPI;
}

The you call it like this:

import withGoogleApps from "./withGoogleApps";

const AppConGoogle = withGoogleApps(App);

Then you can call gogle API's like calendar, for example:

const event = this.buildEventoGoogle(values);

const request = window.gapi.client.calendar.events.insert({
      calendarId: "primary",
      resource: event
});
Related