如何使用 React、Redux 和 Webpack 实现 Google API

Posted

技术标签:

【中文标题】如何使用 React、Redux 和 Webpack 实现 Google API【英文标题】:How to implement Google API with React, Redux and Webpack 【发布时间】:2017-09-28 13:22:51 【问题描述】:

我正在尝试将 Google 日历事件添加到我的 React Redux 应用程序中。 我尝试使用 googleapis 和 google-auth-library 但 webpack 抛出错误,因为 googleapis 是为运行服务器端而构建的,并且 bundle.js 是从客户端引用的。 所以我已经阅读了一些关于这些错误的论坛,它们都指向使用Google's js client library。

我了解如何在 java 或 php 应用程序中实现这一点(我老了...... 35 ;)但我是 React Redux 的新手,我正在寻找实现这一点的最佳方法。

我正在尝试从我的 actions.js 中的日历中获取事件。我尝试在我的 html 标头中包含 <script src="https://apis.google.com/js/api.js"></script>,然后使用 actions.js 中的 gapi.load()。我还尝试创建一个 api.js 文件并使用 require('./api') 引用它。我还尝试使用来自 Node.js Quickstart guide 的 cli 命令来获取 access_token,然后使用 axios 直接调用 Google API,但我得到了 403。我想我只是没有提供正确的标头,但无论如何这都不是最佳做法。

我的问题基本上是如何在遵守 Redux 标准的同时从我的 actions.js 文件中引用 Google 的 js 客户端库?

【问题讨论】:

【参考方案1】:

当我找不到它的 NPM 模块时,你能试试这个库吗:

https://github.com/ded/script.js/

所以你的代码会是这样的:

import $script from 'scriptjs';

$script('https://apis.google.com/js/api.js', function () 
  //Put your google api functions here as callback
);

【讨论】:

【参考方案2】:

在我加载我的 webpack 包 (Option 1) 之前,我会在我的索引文件中加载所有谷歌的东西。然后我会使用redux sagas 调用google api。在你的 webpack 包之前加载谷歌代码将确保当你从 saga 调用 api 时一切准备就绪

【讨论】:

【参考方案3】:

通过在 HTML 标头中包含官方 Google 客户端 API,您走在了正确的轨道上。这不太理想——如果 Google 将(浏览器)客户端 API 作为 npm 模块提供,你可以import 会很好。但他们没有(我看到),所以我认为你正在做的很好。

然后是“我如何以对 React/Redux 友好的方式使用它?”的问题。 Redux 是一种管理应用程序状态的机制。 Google API 不是您的应用程序的一部分(尽管您对它的操作可能会告知您的应用程序的状态)。

验证您是否有权访问 Google API 很容易:您只需从您的一个组件的 componentDidMount 方法进行调用,然后记录控制台日志:

class MyComp extends React.Component 
  componentDidMount() 
    // this is taken directly from Google documentation:
    // https://developers.google.com/api-client-library/javascript/start/start-js
    function start() 
      // 2. Initialize the JavaScript client library.
      gapi.client.init(
        'apiKey': 'YOUR_API_KEY',
        // clientId and scope are optional if auth is not required.
        'clientId': 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
        'scope': 'profile',
      ).then(function() 
        // 3. Initialize and make the API request.
        return gapi.client.request(
          'path': 'https://people.googleapis.com/v1/people/me',
        )
      ).then(function(response) 
        console.log(response.result);
      , function(reason) 
        console.log('Error: ' + reason.result.error.message);
      );
    ;
    // 1. Load the JavaScript client library.
    gapi.load('client', start);
  ,

如果您在控制台上没有看到您所期望的内容,则说明 gapi 未按预期加载。如果发生这种情况,您可以提出更具体的问题!

如果您确实收到了响应,那么您现在知道如何调用 GAPI...但是如何以对 Redux 友好的方式使用它?

当您进行 GAPI 调用时,您可能希望以某种方式修改应用程序的状态(否则为什么要这样做?)例如,您可能会调用身份验证流程,当 GAPI 返回成功时,您的应用程序状态现在有loggedIn: true 或类似的(可能有很多其他的状态变化)。在哪里进行 GAPI 调用取决于您。如果您想在组件加载时执行此操作,则应在componentDidMount 中执行此操作。您通常还可能会发出 GAPI 调用以响应用户操作,例如单击按钮。

所以典型的流程是这样的:

// either in componentDidMount, or a control handler, usually:
someGapiCall()
  .then(result => 
    this.props.onGapiThing(result.whatever)
  )

其中this.props.onGapiThing 是一个调度适当操作的函数,该操作会修改您的应用程序状态。

我希望这个概述能有所帮助...请随时跟进更具体的问题。

【讨论】:

我不得不使用 window.gapi 而不是 gapi【参考方案4】:

尽管有一些非常好的正确答案,我还是要回答我自己的问题。 @MattYao 回答了我的实际问题,即如何在我的 actions.js 文件中获取可供参考的 js 脚本。 @Ethan Brown 给出了一个非常详细的答案,显示了一些出色的流动可能性。 @realseanp 更改了范围,但答案有效。

我尝试了以上所有方法,它们都奏效了。

所以我不确定我做错了什么,但我终于能够通过将<script src="https://apis.google.com/js/api.js"></script> 添加到我的索引头来从actions.js 访问gapi 对象。 我正在使用哈巴狗,所以它看起来像这样:

doctype
html
    head
        title MyTitle
        link(rel='stylesheet' href='/static/css/main.css')
        link(rel='stylesheet' href='/static/css/react-big-calendar.css')
        script(src='https://apis.google.com/js/api.js' type='text/javascript')
    body
        div(id='app')
        script(src='/static/bundle.js' type='text/javascript')

这是我的组件文件:

import React from 'react'
import BigCalendar from 'react-big-calendar';
import moment from 'moment';
import  connect  from 'react-redux'

import  fetchEvents  from '../actions/actions'

BigCalendar.momentLocalizer(moment);
@connect((store) => 
    return 
        events: store.events.events
    
)
export default class Calendar extends React.Component 

    componentWillMount() 
            
        this.props.dispatch(fetchEvents())
    

    render() 
    
        return (
            <div>
                <BigCalendar
                    events=this.props.events
                    startAccessor='startDate'
                    endAccessor='endDate'
                    style=height: 800
                />
            </div>
        )
    

然后我可以在我的 actions.js 文件中使用它

export function fetchEvents() 

  return (dispatch) =>
  
    function start() 
    
      // 2. Initialize the JavaScript client library.
      gapi.client.init(
        'apiKey': API_KEY,
        // clientId and scope are optional if auth is not required.
        'clientId': CLIENT_ID,
        'scope': 'profile',
      ).then(function() 
        // 3. Initialize and make the API request.
        return gapi.client.request(
          'path': 'https://www.googleapis.com/calendar/v3/calendars/MY_EMAIL@gmail.com/events?timeMax=2017-06-03T23:00:00Z&timeMin=2017-04-30T00:00:00Z',
        )
      ).then( (response) => 
        let events = response.result.items
        dispatch( 
          type: 'FETCH_EVENTS_FULFILLED',
          payload: events
        )
      , function(reason) 
        console.log(reason);
      );
    ;

    // 1. Load the JavaScript client library.
    gapi.load('client', start)

我必须公开我的日历才能以这种方式访问​​它。所以现在我要研究 oauth2 的东西:/

【讨论】:

【参考方案5】:

试试这个包。 看起来它已经更新了。 https://github.com/QuodAI/tutorial-react-google-api-login

【讨论】:

以上是关于如何使用 React、Redux 和 Webpack 实现 Google API的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 react、redux 和 graphql 解决“未定义的 proptype”错误

如何组织 Redux Action-Creators 以在 Redux-React 中使用

如何使用来自 react-redux-firebase 的 redux thunk getFireBase 和 getFirestore 将数据添加到 firebase doc

如何使用 thunk 和 useDispatch(react-redux 挂钩)从操作中返回承诺?

使用 React-Router 和 Redux 时单击链接时如何调度操作?

如何使用 React 和 Redux 从另一个组件访问 ref?