最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to Integrate Google Calendar API with React JS? - Stack Overflow

programmeradmin4浏览0评论

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';
    var DISCOVERY_DOCS = [""];
    var SCOPES = "";
    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
      })
      //listUpingEvents();
      //insertNewEvent();
    } else {
      this.setState({
        showAuthButton: true,
        showSignOutButton: false
      })
    }
  }
  ponentDidMount(){
    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...

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.';
    var DISCOVERY_DOCS = ["https://www.googleapis./discovery/v1/apis/calendar/v3/rest"];
    var SCOPES = "https://www.googleapis./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
      })
      //listUpingEvents();
      //insertNewEvent();
    } else {
      this.setState({
        showAuthButton: true,
        showSignOutButton: false
      })
    }
  }
  ponentDidMount(){
    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...

Share Improve this question edited Jul 22, 2017 at 16:18 Sivadass N asked Jul 22, 2017 at 15:40 Sivadass NSivadass N 9274 gold badges12 silver badges23 bronze badges 6
  • You defined CLIENT_ID etc as variables in constructor but trying to access it as this.CLIENT_ID – marzelin Commented Jul 22, 2017 at 16:07
  • @marzelin I have updated the code now, still getting the same error! – Sivadass N Commented Jul 22, 2017 at 16:19
  • Either move config vars outside the ponent so that is can be reached by initClient method, or assign config data to this object and access it that way. – marzelin Commented Jul 22, 2017 at 16:22
  • still getting the same error – Sivadass N Commented Jul 22, 2017 at 16:37
  • It's hard to tell what's going on without having access to the whole app. Could you upload your code to github so that I could clone it and reproduce the error? – marzelin Commented Jul 22, 2017 at 16:41
 |  Show 1 more ment

3 Answers 3

Reset to default 5

Finally adding my solution which worked to help future ers :)

To get the list of events, authorization is not required. So removed the unnecessary code from google's quickstart example.

ponentDidMount = () => {
  this.getEvents();
}

getEvents(){
  let that = this;
  function start() {
    gapi.client.init({
      'apiKey': GOOGLE_API_KEY
    }).then(function() {
      return gapi.client.request({
        'path': `https://www.googleapis./calendar/v3/calendars/${CALENDAR_ID}/events`,
      })
    }).then( (response) => {
      let events = response.result.items
      that.setState({
        events
      }, ()=>{
        console.log(that.state.events);
      })
    }, function(reason) {
      console.log(reason);
    });
  }
  gapi.load('client', start)
}

You can find the full code and functional demo here.

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

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

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

    ponentDidMount() {
      this.loadGoogleAPI();
    }

    loadGoogleAPI() {
      const script = document.createElement("script");
      script.src = "https://apis.google./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
});

You moved gapi config variables outside of the ponent, but didn't remove them from initClient parameters so they couldn't be accessed. Here's proper code:

var CLIENT_ID = '992549188018-3prg54pp18je3e3qhgcttgl11491c4dm.apps.googleusercontent.';
var DISCOVERY_DOCS = ["https://www.googleapis./discovery/v1/apis/calendar/v3/rest"];
var SCOPES = "https://www.googleapis./auth/calendar";

class App extends React.Component{
  constructor(props) {
    super(props);
    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(/****here you've had parameters that made config vars unaccessible*****/) {
    gapi.client.init({
      discoveryDocs: DISCOVERY_DOCS,
      clientId: CLIENT_ID,
      scope: SCOPES
    }).then(function () {
      console.log(window.gapi);
      // Listen for sign-in state changes.

      // ************* to access instance method you have to use `this.updateSigninStatus`  
  window.gapi.auth2.getAuthInstance().isSignedIn.listen(this.updateSigninStatus);

      // Handle the initial sign-in state.
      updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());

      // **************this code is unnecessary and causes errors***** 
      // authorizeButton.onclick = handleAuthClick;
      // signoutButton.onclick = handleSignoutClick;
    });
  }
  updateSigninStatus(isSignedIn) {
    if (isSignedIn) {
      this.setState({
        showAuthButton: false,
        showSignOutButton: true
      })
      //listUpingEvents();
      //insertNewEvent();
    } else {
      this.setState({
        showAuthButton: true,
        showSignOutButton: false
      })
    }
  }
  ponentDidMount(){
    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')
);
发布评论

评论列表(0)

  1. 暂无评论