web-dev-qa-db-fra.com

Comment implémenter l'API Google avec React, Redux et Webpack

J'essaie d'intégrer des événements d'agenda Google dans mon application React Redux.
J'ai essayé d'utiliser googleapis et google-auth-library, mais Webpack génère des erreurs, car googleapis a été créé pour exécuter côté serveur et bundle.js est référencé à partir du client. J'ai donc lu quelques forums à propos de ces erreurs et ils ont tous tendance à utiliser la bibliothèque cliente js de Google

Je comprends comment implémenter ceci dans une application Java ou php (je suis vieux ... 35;) mais je suis nouveau dans React Redux et je cherche le meilleur moyen de le mettre en oeuvre. 

J'essaie d'extraire les événements de mon calendrier dans mes actions.js. J'ai essayé d'inclure <script src="https://apis.google.com/js/api.js"></script> dans mon en-tête HTML, puis d'utiliser gapi.load () à partir d'actions.js. J'ai également essayé de créer un fichier api.js et de le référencer avec require ('./ api'). J'ai également essayé d'utiliser les commandes cli du Node.js Guide de démarrage rapide pour obtenir un access_token, puis il suffit d'utiliser axios pour appeler directement l'API Google, mais je reçois un 403. Je pense que je ne le suis tout simplement pas. fournir les en-têtes appropriés, mais ce ne serait de toute façon pas la meilleure pratique.

Ma question est la suivante: comment référencer la bibliothèque cliente js de Google à partir de mon fichier actions.js tout en respectant les normes Redux?

7
pnkflydgr

Je vais répondre à ma propre question malgré de très bonnes réponses correctes. @ MattYao a répondu à ma question de savoir comment obtenir un script js disponible comme référence dans mon fichier actions.js. @ Ethan Brown a donné une réponse très détaillée qui montrait d'excellentes possibilités d'écoulement. @ Realseanp a changé la portée, mais une réponse valable.

J'ai essayé tout ce qui précède et ils ont travaillé.

Donc, je ne suis pas sûr de ce que je faisais mal mais j'ai finalement pu accéder à l'objet gapi depuis actions.js en ajoutant simplement <script src="https://apis.google.com/js/api.js"></script> à ma tête d'index. J'utilise pug, il se présente ainsi:

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

Voici mon fichier de composant:

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>
        )
    }
}

Et puis, j'ai pu le faire fonctionner dans mon fichier 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/[email protected]/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)
}}

Je devais rendre mon calendrier public pour y accéder de cette façon. Alors maintenant, je vais travailler sur le truc oauth2: /

1
pnkflydgr

Pouvez-vous essayer cette bibliothèque avec laquelle j'avais l'habitude de charger des bibliothèques et des modules externes dans l'application React lorsque je ne trouvais pas de module NPM pour elle: 

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

Donc, votre code sera comme ça:

import $script from 'scriptjs';

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

Vous êtes sur la bonne voie en incluant l'API client Google officielle dans l'en-tête HTML. Ce n'est pas idéal - ce serait bien si Google fournissait l'API client (navigateur) sous la forme d'un module npm que vous pourriez import. Mais ils ne le font pas (ce que je vois), alors je pense que ce que vous faites est bien.

Ensuite, il y a la question de "comment puis-je l'utiliser de manière conviviale avec React/Redux?" Redux est un mécanisme permettant de gérer l’état de votre application . L'API de Google ne fait pas partie de votre application (bien que son utilisation puisse informer de l'état de votre application).

Il est facile de vérifier que vous avez accès à l'API Google: vous pouvez simplement appeler à partir de la méthode componentDidMount de l'un de vos composants et créer un journal de console:

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);
  },
}

Si vous ne voyez pas ce que vous attendez sur la console, gapi ne sera pas chargé comme prévu. Si cela se produit, vous aurez une question plus précise à poser!

Si vous obtenez une réponse, vous savez maintenant comment appeler GAPI ... mais alors comment l'utiliser de manière conviviale pour Redux?

Lorsque vous passez un appel GAPI, vous souhaiterez probablement modifier l’état de votre application (sinon, pourquoi le feriez-vous?) Par exemple, vous pouvez appeler le flux d’authentification et lorsque GAPI renvoie le résultat obtenu, votre état de l’application a maintenant loggedIn: true ou similaire (éventuellement avec beaucoup d'autres changements d'état). Vous choisissez l’appel GAPI. Si vous voulez le faire lors du chargement du composant, vous devez le faire dans componentDidMount. Vous pouvez également généralement passer un appel GAPI en réponse à une action de l'utilisateur, par exemple en cliquant sur un bouton.

Ainsi, le flux typique serait quelque chose comme ceci:

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

this.props.onGapiThing est une fonction qui distribue une action appropriée, qui modifie l'état de votre application.

J'espère que cet aperçu vous aidera ... n'hésitez pas à poser des questions plus spécifiques.

3
Ethan Brown

Je voudrais charger tous les trucs Google dans mon fichier d'index avant de charger mon paquet Webpack ( Option 1 ). Ensuite, je voudrais utiliser redux sagas pour appeler le Google Apis. Charger le code google avant que votre paquet Webpack ne vous assure que tout est prêt à partir lorsque vous appelez l’API de la saga

0
pizza-r0b