title: Google Calendar API with React
body: <p>I'm trying to use Google Calendar API in a React and Firebase app. I'm authenticating to Google in my <code>App.js</code> component, while I attempt to access the Google Calendar API in my <code>Calendar.js</code> component.</p>
  
  <p>Here's my <code>App.js</code>:</p>
  
  <pre><code>import React from 'react'
  import firebase from 'firebase'
  import './App.css'
  import AppBody from '../AppBody'
  import AppHeader from '../AppHeader'
  
  
  class App extends React.Component {
  
    constructor() {
      super()
      this.state = {
        user: null,
        googleAuth: null
      }
    }
  
    componentDidMount() {
  
      // capture authentication callback
      firebase.auth().onAuthStateChanged(user =&gt; {
        if (user !== this.state.user) {
          this.setState({user})
        }
      })
  
      const script = document.createElement('script')
      script.src = 'https://apis.google.com/js/api.js'
  
      script.onload = () =&gt; {
        window.gapi.load('client:auth2', () =&gt; {
          window.gapi.client.init({
            clientId: 'client_Id',
            scope: 'https://www.googleapis.com/auth/calendar'
          }).then(() =&gt;
            this.setState({googleAuth: window.gapi.auth2.getAuthInstance()})
          )
        })
      }
  
      document.head.appendChild(script)
    }
  
    handleAuthClick = () =&gt; {
  
      let {googleAuth} = this.state
  
      if (this.state.user) {
  
        googleAuth.signOut().then(firebase.auth().signOut())
  
      } else {
  
        googleAuth.signIn().then(googleUser =&gt; {
  
            var unsubscribe = firebase.auth().onAuthStateChanged(firebaseUser =&gt; {
              unsubscribe()
  
              if (!isUserEqual(googleUser, firebaseUser)) {
  
                var credential = firebase.auth.GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token)
                firebase.auth().signInWithCredential(credential)
                  .then(user =&gt; this.setState({user}))
                  .catch(error =&gt; console.error(error))
  
              } else {
  
                console.log('User already signed-in Firebase.')
                console.log(googleUser)
              }
            })
        })
  
        let isUserEqual = (googleUser, firebaseUser) =&gt; {
          if (firebaseUser) {
            var providerData = firebaseUser.providerData
            for (let i = 0; i &lt; providerData.length; i++) {
              if (providerData[i].providerId === firebase.auth.GoogleAuthProvider.PROVIDER_ID &amp;&amp;
                  providerData[i].uid === googleUser.getBasicProfile().getId()) {
                return true
              }
            }
          }
          return false
        }
      }
    }
  
    render() {
  
      let {user} = this.state
  
      return (
        &lt;div&gt;
          &lt;AppHeader onAuthClick={this.handleAuthClick} user={user} /&gt;
          {user ? &lt;AppBody userID={user.uid} /&gt; : undefined}
        &lt;/div&gt;
      )
    }
  }
  
  export default App
  </code></pre>
  
  <p>And here is my <code>Calendar.js</code> (it's loaded by the AppBody component)</p>
  
  <pre><code>import React from 'react'
  import './Calendar.css'
  
  
  class Calendar extends React.Component {
  
    constructor(props) {
      super(props)
      this.state = {
        events: []
      }
    }
  
    componentDidMount() {
  
      if (window.gapi &amp;&amp; window.gapi.client) {
  
        var timeMin = new Date()
        timeMin.setHours(0, 0, 0)
  
        var timeMax = new Date()
        timeMax.setHours(23, 59, 59)
  
        window.gapi.client.load('calendar', 'v3', () =&gt; {
          window.gapi.client.calendar.events.list({
            'calendarId': 'primary',
            'timeMin': timeMin.toISOString(),
            'timeMax': timeMax.toISOString(),
            'singleEvents': true
          }).then(response =&gt; {
            let events = []
            response.result.items.forEach(event =&gt; {
              events.push({
                title: event.summary,
                start: new Date(event.start.dateTime),
                end: new Date(event.end.dateTime)
              })
            })
            this.setState({events})
          })
        })
      }
    }
  
    render() {
  
      console.log(this.state.events)
  
      return (
        ...render events...
      )
    }
  }
  
  export default Calendar
  </code></pre>
  
  <p>The problem is, if I keep refreshing the screen, I get very inconsistent results:</p>
  
  <ul>
  <li>Sometimes I get and render the list of events.</li>
  <li>More often than not, I get no events.</li>
  <li>On occasion, I get the following error:</li>
  </ul>
  
  <p><code>Uncaught {result: {…}, body: "{↵ "error": {↵  "errors": [↵   {↵    "domain": "us…e Exceeded. Continued use requires signup."↵ }↵}↵", headers: {…}, status: 403, statusText: null}</code></p>
  
  <p>I'm obviously not using the Calendar API correctly. What am I doing wrong though?</p>