Использование кнопки входа в Google с реакцией

Я пытаюсь использовать вход Google в приложении для реагирования. Хотя использование кнопки входа вне самого приложения отлично работает, при использовании ее в пользовательском компоненте входа я не могу заставить ее работать должным образом. Когда пользователь входит в систему, сама кнопка должна выполнять метод data-onsuccess. Проблема в том, что выполнение никогда не достигает этого метода, хотя вход работает.

Вероятно, мне не хватает какой-то реакции, но я не могу ее найти. Любая помощь? Найдите ниже html, который загружает все и сам компонент.

<head>
    <meta name="google-signin-scope" content="profile email">
    <meta name="google-signin-client_id" content="1234-real-client-id.apps.googleusercontent.com">
    <script src="https://apis.google.com/js/platform.js" async defer></script>
</head>
<body>
    <!-- Here is where everything gets displayed -->
    <div id="app"></div>

    <!-- The file with the js code -->
    <script src="/js/main.js"></script>
</body>


var SignIn = React.createClass({
    onSignIn : function (google_user) {
        // I want this method to be executed
    },

    render : function() {
        return (
            <div className="g-signin2" data-onsuccess={this.onSignIn} data-theme="dark" />
        );
    }
});

Обратите внимание, что я не вставил сюда нерелевантный код;)


person ThisIsErico    schedule 24.07.2015    source источник
comment
В этом видео рассказывается о Google, Facebook и Linked In для входа в систему с помощью reactjs -youtu.be/9MhLHkf7Ifs   -  person Prem    schedule 04.08.2017


Ответы (6)


Попробуйте добавить обратный вызов onSuccess при инициализации компонента в componentDidMount().

componentDidMount: function() {
  gapi.signin2.render('g-signin2', {
    'scope': 'https://www.googleapis.com/auth/plus.login',
    'width': 200,
    'height': 50,
    'longtitle': true,
    'theme': 'dark',
    'onsuccess': this. onSignIn
  });  
},
...

Источники: https://developers.google.com/identity/sign-in/web/build-button, https://github.com/meta-meta/webapp-template/blob/6d3e9c86f5c274656ef799263c84a228bfbe1725/app/Application/signIn.jsx.

person BradByte    schedule 24.07.2015
comment
Это на самом деле работает просто отлично! :) Я думаю, что реакция на самом деле не добавляет правильный атрибут данных. Большое спасибо Брэд! - person ThisIsErico; 24.07.2015
comment
Большое спасибо за ссылку на коммит, а не на /master или /develop, как это делает большинство людей. Ты святой, @BradBumbalough!!!! - person Chris Browne; 01.12.2016
comment
Обратите внимание: удалите строку scope, если вы не хотите запрашивать эти разрешения. - person spencer.sm; 27.02.2019

Мне нужно было использовать это в функциональном компоненте, поэтому я решил поделиться тем, как я его адаптировал, мне нужно было использовать useEffectHook, который можно использовать вместо componentDidMount.

  useEffect(() => {
    window.gapi.signin2.render('g-signin2', {
      'scope': 'https://www.googleapis.com/auth/plus.login',
      'width': 200,
      'height': 50,
      'longtitle': true,
      'theme': 'dark',
      'onsuccess': onSignIn
    })
  })
person Max Carroll    schedule 30.07.2019
comment
Я попробовал ваш код, но onsuccess не срабатывает. Любая другая настройка, которая требуется? - person Ejaz; 03.09.2019
comment
не уверен, что это может быть, я передаю свой метод onsuccess в качестве опоры от родительского узла, пробовали ли вы очевидные вещи путем отладки и обеспечения того, чтобы ваш обратный вызов onsuccess был определен в точке выполнения, возможно, установите точку останова в окне .gapi в строке 2 и убедитесь, что туда не передается null, в противном случае эту функцию следует вызывать после завершения процесса входа (например, после выбора и учетной записи, ввода пароля и утверждения любых областей, требующих утверждения) - Но чтобы ответить на ваш вопрос, все остальное, что требуется, это определить onSignIn - person Max Carroll; 23.09.2019
comment
@Ejaz Может быть, проверьте мой ответ: stackoverflow.com/a/59040581/996314 - person Rokit; 26.11.2019
comment
Моя решена с помощью GoogleAuth.isSignedIn.listen() на основе developers.google.com/identity/sign-in/web/reference. Это происходит так window.gapi.load('auth2', () => { const auth2 = window.gapi.auth2.init({ config goes here }); auth2.isSignedIn.listen(() => { your code here }) }) . Если вы хотите получить профиль пользователя, вы можете использовать GoogleUser.getBasicProfile(). Надеюсь это поможет. - person Yor; 05.02.2020

Теперь вы можете использовать этот React Google Login пакет NPM, который инкапсулирует всю работу по настройке. . Вы можете просто передать параметры только компоненту.

import React from 'react';
import ReactDOM from 'react-dom';
import GoogleLogin from 'react-google-login';
// or
import { GoogleLogin } from 'react-google-login';
 
 
const responseGoogle = (response) => {
  console.log(response);
}
 
ReactDOM.render(
  <GoogleLogin
    clientId="658977310896-knrl3gka66fldh83dao2rhgbblmd4un9.apps.googleusercontent.com"
    buttonText="Login"
    onSuccess={responseGoogle}
    onFailure={responseGoogle}
    cookiePolicy={'single_host_origin'}
  />,
  document.getElementById('googleButton')
);

Код взят из документации пакета.

person AV Paul    schedule 07.08.2019
comment
реакция-гугл-логин сработала отлично! Мне пришлось использовать как состояние реакции, так и локальное хранилище, чтобы получить обновление после входа в систему. то есть: onSuccess={(response) => { this.setState({ userLoggedIn: true, }, () => { localStorage.setItem('userLoggedIn', true); }); - person Miguel Reyes; 17.08.2019

Может быть немного поздно, но я хочу поделиться своим ходом реализации. Так как в моем случае я хочу полностью настроить кнопку, а также хочу иметь какой-то загрузчик. Я повторно реализовал это, используя хуки

/* istanbul ignore file */
import { useState, useEffect, useCallback } from 'react';
import { APP_IDS } from 'utils/constants';

const initgAuth = () =>
  // eslint-disable-next-line no-unused-vars
  new Promise((resolve, _reject) => {
    // eslint-disable-next-line no-undef
    gapi.load('auth2', () => {
      // eslint-disable-next-line no-undef
      const auth = gapi.auth2.init({
        client_id: APP_IDS.Google,
      });
      resolve(auth);
    });
  });

const initializeGoogle = () =>
  // eslint-disable-next-line no-unused-vars
  new Promise((resolve, _reject) => {
    if (typeof gapi !== 'undefined') {
      window.googleAsyncInit().then(auth => {
        resolve(auth);
      });
    } else {
      // eslint-disable-next-line func-names
      window.googleAsyncInit = async function() {
        const auth = await initgAuth();
        resolve(auth);
        return auth;
      };

      // eslint-disable-next-line func-names
      (function(d, s, id) {
        let js;
        const gjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {
          return;
        }
        // eslint-disable-next-line prefer-const
        js = d.createElement(s);
        js.id = id;
        js.src = 'https://apis.google.com/js/platform.js';
        js.onload = window.googleAsyncInit;
        gjs.parentNode.insertBefore(js, gjs);
      })(document, 'script', 'google_api');
    }
  });

const useGoogle = () => {
  const [google, setGoogle] = useState([]);
  const [isReady, setReady] = useState(false);

  const initGoogle = useCallback(async () => {
    const auth = await initializeGoogle();
    if (auth !== 'undefined') {
      setGoogle(auth);
      setReady(true);
    }
  });

  useEffect(() => {
    initGoogle();
  }, [initGoogle]);

  return [google, isReady];
};

Так что я могу просто использовать это в любом компоненте, подобном этому

  const [GoogleInstance, isGoogleReady] = useGoogle();

   GoogleInstance.signIn().then(response => {
      const authResponse = response.getAuthResponse(true);
      doGoogleLogin(authResponse);
    });

Это довольно удобно, потому что я могу убедиться, что SDK загружен, прежде чем пользователь сможет взаимодействовать с самой кнопкой. Также можно использовать, если у вас есть разные компоненты/страницы, для которых требуется вход в Google.

person keysl    schedule 21.04.2021

Просто убедитесь, что вы добавили тег скрипта Google platform.js в тег index.html вашего приложения React:

<script src="https://apis.google.com/js/platform.js" async defer></script>

Получите идентификатор клиента от:

https://console.developers.google.com/apis/credentials


EDIT Обновленный пример с реальной реализацией, которую я использую в развернутых рабочих приложениях

А вот пример реализации функционального компонента SignInWithGoogle в Typescript, который вы можете использовать в качестве вдохновения:

// window.ts
export {};

declare global {
  interface Window {
    gapi: any;
  }
}


// index.tsx
import './window';

import React, {
  useEffect,
  useState,
} from 'react';

const SignInWithGoogle = () => {
  const [loaded, setLoaded] = useState<boolean>(false);
  const [signedIn, setSignedIn] = useState<boolean>(false);

  const onSignIn = (googleUser: {[k: string]: any}) => {
    if (!signedIn) {
      setSignedIn(true);

      const token = googleUser.getAuthResponse().id_token;

      // do something with the token (like send it to your api)...
    }
  };

  const onFail = ({
    error,
  }: {
    error: string;
  }) => {
    // do something
  };

  useEffect(() => {
    const { gapi } = window;

    if (!loaded) {
      gapi.load('auth2', () => {
        gapi.auth2.init().then((auth: any) => {
          auth.signOut().then(() => {
            gapi.signin2.render('google-signin-button', {
              width: 232,
              height: 40,
              longtitle: true,
              onsuccess: onSignIn,
              onfailure: onFail,
            });
          });
        });

        setLoaded(true);
      });
    }
  });

  return (
    <div
      id="google-signin-button"
      className="google-signin-button"
    />
  );
};

export default SignInWithGoogle;
person JeanLescure    schedule 25.11.2020

Ни один из других ответов не работал для меня. В конечном итоге сработало использование идентификатора вместо класса для идентификатора в div.

<div id="g-signin2" />

вместо

<div className="g-signin2" />

В дополнение к использованию window.gapi.signin2.render, как предполагают другие ответы.

person Alex L    schedule 11.12.2020