" GAPI未定义"信息

时间:2016-10-18 16:00:29

标签: javascript reactjs google-sheets

我尝试使用Google表格API包含在我的网络应用中,但我一直收到错误,指出未定义gapi库。我尝试使用ComponentDidMount生命周期方法将请求延迟到服务器,甚至在该方法中使用超时,但我仍然收到相同的错误。如何在我的应用程序中定义使用gapi库?

import React from 'react';
var CLIENT_ID = ''; 
var SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"];


export default class MyNavbar extends React.Component {

  constructor(props) {
    super(props);
  }

  componentDidMount(){
     this.checkAuth();

   }

      /**
       * Check if current user has authorized this application.
       */      
    checkAuth(){
        gapi.auth.authorize(
          {
            'client_id': CLIENT_ID,
            'scope': SCOPES.join(' '),
            'immediate': true
          }, this.handleAuthResult());
      }

      /**
       * Handle response from authorization server.
       *
       * @param {Object} authResult Authorization result.
       */
      handleAuthResult(authResult) {
        var authorizeDiv = document.getElementById('authorize-div');
        if (authResult && !authResult.error) {
          // Hide auth UI, then load client library.
          authorizeDiv.style.display = 'none';
          loadSheetsApi();
        } else {
          // Show auth UI, allowing the user to initiate authorization by
          // clicking authorize button.
          authorizeDiv.style.display = 'inline';
        }
      }

      /**
       * Initiate auth flow in response to user clicking authorize button.
       *
       * @param {Event} event Button click event.
       */
     handleAuthClick(event) {
        gapi.auth.authorize(
          {client_id: CLIENT_ID, scope: SCOPES, immediate: false},
          handleAuthResult);
        return false;
      }

      /**
       * Load Sheets API client library.
       */
     loadSheetsApi() {
        var discoveryUrl =
            'https://sheets.googleapis.com/$discovery/rest?version=v4';
        gapi.client.load(discoveryUrl).then(listMajors);
      }

      /**
       * Print the names and majors of students in a sample spreadsheet:
       * https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
       */
      listMajors() {
        gapi.client.sheets.spreadsheets.values.get({
          spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
          range: 'Class Data!A2:E',
        }).then(function(response) {
          var range = response.result;
          if (range.values.length > 0) {
            appendPre('Name, Major:');
            for (i = 0; i < range.values.length; i++) {
              var row = range.values[i];
              // Print columns A and E, which correspond to indices 0 and 4.
              appendPre(row[0] + ', ' + row[4]);
            }
          } else {
            appendPre('No data found.');
          }
        }, function(response) {
          appendPre('Error: ' + response.result.error.message);
        });
      }

      /**
       * Append a pre element to the body containing the given message
       * as its text node.
       *
       * @param {string} message Text to be placed in pre element.
       */
      appendPre(message) {
        var pre = document.getElementById('output');
        var textContent = document.createTextNode(message + '\n');
        pre.appendChild(textContent);
      }


   render(){
      return (
        <div>
          <h1>Hello World My Name Is Justin 2</h1>
          <div id="authorize-div"></div>
          <pre id="output"></pre>   
        </div>
      );
    }
}

4 个答案:

答案 0 :(得分:1)

试试这个。

import React from 'react';
import asyncLoad from 'react-async-loader'; // for loading script tag asyncly `npm i --save react-async-loader`

const CLIENT_ID = '';
const SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"];

// For making gapi object passed as props to our component
const mapScriptToProps = state => ({
   // gapi will be this.props.gapi
   gapi: {
      globalPath: 'gapi',
      url: 'https://your-gapi-url'
   }
});

@asyncLoad(mapScriptToProps)
class MyNavbar extends React.Component {

  constructor(props) {
    super(props);
    this.gapi = null;
    // You need to bind methods to this class's object context. (i.e this)!
    this.checkAuth = this.checkAuth.bind(this);
    this.handleAuthResult = this.authResult.bind(this);
    this.handleAuthClick = this.handleAuthClick.bind(this);
    this.loadSheetsApi = this.loadSheetsApi.bind(this);
    this.listMajors = this.listMajors.bind(this);
  }

  componentDidMount() {
    // Check is gapi loaded?
    if (this.props.gapi !== null) {
       this.checkAuth();
    }
  }

  componentWillReceiveProps({ gapi }) {
    if (gapi!== null) {
      this.checkAuth();
    }
  }

   /**
   * Check if current user has authorized this application.
   */
  checkAuth() {

    // this will give you an error of gapi is not defined because there is no
    // reference of gapi found globally you cannot access global object which are
    // not predefined in javascript( in this case its window.gapi ).
    // properties added by Programmer cannot be accessed directly( if it's not in the same file as well as the same scope!) in commonjs modules. Because they
    // don't' run in a global scope. Any variable in another module which is not
    // exported, will not be available to other modules.

    this.gapi = window.gapi; // you can do like this. Now you can access gapi in all methods if this class.
    this
        .gapi
        .auth
        .authorize({
            'client_id': CLIENT_ID,
            'scope': SCOPES.join(' '),
            'immediate': true
        }, this.handleAuthResult());
  }

   /**
   * Handle response from authorization server.
   *
   * @param {Object} authResult Authorization result.
   */
  handleAuthResult(authResult) {
    var authorizeDiv = document.getElementById('authorize-div');
    if (authResult && !authResult.error) {
        // Hide auth UI, then load client library.
        authorizeDiv.style.display = 'none';
        loadSheetsApi();
    } else {
        // Show auth UI, allowing the user to initiate authorization by clicking
        // authorize button.
        authorizeDiv.style.display = 'inline';
    }
  }

  /**
   * Initiate auth flow in response to user clicking authorize button.
   *
   * @param {Event} event Button click event.
   */
  handleAuthClick(event) {
    // gapi.auth.authorize(  here also gapi is not defined  
     this
        .gapi
        .auth
        .authorize({
            client_id: CLIENT_ID,
            scope: SCOPES,
            immediate: false
        }, handleAuthResult);
    return false;
  }

  /**
   * Load Sheets API client library.
   */
  loadSheetsApi() {
    var discoveryUrl = 'https://sheets.googleapis.com/$discovery/rest?version=v4';
    // also will give your error
    // for gapi being not defined.
    // gapi.client.load(discoveryUrl).then(listMajors); 
    this
        .gapi
        .client
        .load(discoveryUrl)
        .then(listMajors);
  }

  /**
   * Print the names and majors of students in a sample spreadsheet:
   * https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
   */
  listMajors() {
    this.gapi
        .client
        .sheets
        .spreadsheets
        .values
        .get({spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms', range: 'Class Data!A2:E'})
        .then(function (response) {
            var range = response.result;
            if (range.values.length > 0) {
                appendPre('Name, Major:');
                for (i = 0; i < range.values.length; i++) {
                    var row = range.values[i];
                    // Print columns A and E, which correspond to indices 0 and 4.
                    appendPre(row[0] + ', ' + row[4]);
                }
            } else {
                appendPre('No data found.');
            }
        }, function (response) {
            appendPre('Error: ' + response.result.error.message);
        });
  }

 /**
   * Append a pre element to the body containing the given message
   * as its text node.
   *
   * @param {string} message Text to be placed in pre element.
   */
  appendPre(message) {
    // as you can see. You are accessing window.document as document. 
    // its fine because its defined in javascript (implicitly),
    // not explicitly by programmer(here you!).
    var pre = document.getElementById('output'); 
    var textContent = document.createTextNode(message + '\n');
    pre.appendChild(textContent);
  }

  render() {
    return (
        <div>
            <h1>Hello World My Name Is Justin 2</h1>
            <div id="authorize-div"></div>
            <pre id="output"></pre>
        </div>
    );
  }
}

export default MyNavbar;

答案 1 :(得分:0)

您需要在index.html文件中的bundle.js之前加载gapi库,或者您可以使用 react-async-loader gapi js脚本async。 >。 以下是如何做到的:

import React, { Component, PropTypes } from 'react';
import asyncLoad from 'react-async-loader'; // for loading script tag asyncly

// For making gapi object passed as props to our component
const mapScriptToProps = state => ({
   gapi: {
     globalPath: 'gapi',
     url: 'https://your-gapi-url'
   }
});
// decorate our component
@asyncLoad(mapScriptToProps)
class yourComponent extends Component {
    componentDidMount() {
      // Check is gapi loaded?
      if (this.props.gapi !== null) {
         this.checkAuth();
      }
    }

    componentWillReceiveProps({ gapi }) {
      if (gapi!== null) {
        this.checkAuth();
      }
    }

    checkAuth = () => {
      // Better check with window and make it available in component
      this.gapi = window.gapi;
      this.gapi.auth.authorize({
        'client_id': CLIENT_ID,
        'scope': SCOPES.join(' '),
        'immediate': true
      }, this.handleAuthResult);
    }

    handleAuthResult = (authData) => {
       // Your auth loagic...
    }

    render() {
       return ( <div>
                  { this.props.gapi &&
                    <YourSpreadsheetOrWhatever data={ this.getData() } />
                  }
            </div>)
    }
}

尝试用此替换您的代码并检查它是否有效。

答案 2 :(得分:0)

我发现这个项目https://github.com/rlancer/gapi-starter可能会有所帮助。

Google登录&amp; API + ReactJS + Flow + Webpack入门套件

Google API非常棒,但它们是在Javascript编程的模块合作伙伴变得流行之前设计的。此入门手册修复了为您处理Google登录和库加载的问题。

获取代码!

git clone https://github.com/rlancer/gapi-starter.git cd gapi-starter npm install

答案 3 :(得分:0)

您需要将index.html文件中的bundle.js之前的gapi库加载为:

<script src="https://apis.google.com/js/api.js"></script>

然后您只需要将gapi变量初始化为:

let gapi = window.gapi;