【问题标题】:How to Integrate Google Calendar API with React JS?如何将 Google Calendar API 与 React JS 集成?
【发布时间】:2017-12-28 14:35:06
【问题描述】:

我正在尝试在 react js 应用程序中实现 this vanilla js 示例的 google 日历 api。 vanilla JS 示例在我的本地机器上运行良好。但是在反应中实施同样的事情时遇到了很多麻烦。请检查下面的代码:

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')
);

目前收到此错误:

未捕获的类型错误:无法读取 null 的属性“isSignedIn”

请指导我进一步前进...

【问题讨论】:

  • 您将CLIENT_ID 等定义为构造函数中的变量,但试图以this.CLIENT_ID 的形式访问它
  • @marzelin 我已经更新了代码,仍然出现同样的错误!
  • 要么将配置变量移到组件外,以便可以通过initClient 方法访问,要么将配置数据分配给this 对象并以这种方式访问​​它。
  • 仍然出现同样的错误
  • 如果无法访问整个应用程序,很难知道发生了什么。您能否将您的代码上传到 github,以便我可以克隆它并重现错误?

标签: javascript reactjs calendar google-api-js-client google-calendar-api


【解决方案1】:

我正在使用 HOC 来加载 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;
}

你这样称呼它:

import withGoogleApps from "./withGoogleApps";

const AppConGoogle = withGoogleApps(App);

然后就可以调用gogle API之类的日历了,例如:

const event = this.buildEventoGoogle(values);

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

【讨论】:

    【解决方案2】:

    最后添加我的解决方案来帮助未来的人:)

    要获取事件列表,不需要授权。所以从谷歌的快速入门示例中删除了不必要的代码。

    componentDidMount = () => {
      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.com/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)
    }
    

    你可以找到完整的代码和功能演示here

    【讨论】:

      【解决方案3】:

      您将 gapi 配置变量移到组件之外,但没有从 initClient 参数中删除它们,因此无法访问它们。 这是正确的代码:

      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";
      
      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
            })
            //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')
      );
      

      【讨论】:

      • 我不知道哪里出错了,谢谢你的帮助和时间:)
      猜你喜欢
      • 1970-01-01
      • 2019-06-29
      • 2019-12-25
      • 1970-01-01
      • 2021-02-16
      • 2022-11-19
      • 1970-01-01
      • 2020-12-23
      • 2021-06-12
      相关资源
      最近更新 更多