我正在尝试在反应应用程序中使用谷歌登录。
虽然在应用程序外部使用登录按钮本身很有效,但在自定义SignIn组件中使用它时,我无法按预期工作。
当用户登录时,按钮本身应该执行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" />
);
}
});
请注意,我没有在此处粘贴不相关的代码;)
答案 0 :(得分:27)
在componentDidMount()
初始化组件时尝试添加onSuccess回调。
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。
答案 1 :(得分:1)
我需要在功能组件中使用它,以为我会分享如何修改它,我需要使用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
})
})
答案 2 :(得分:1)
现在,您可以使用此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')
);
该代码来自软件包的文档。
答案 3 :(得分:0)
只需确保将Google的platform.js
脚本标签添加到React应用的index.html
:
<script src="https://apis.google.com/js/platform.js" async defer></script>
从以下位置获取您的客户ID:
https://console.developers.google.com/apis/credentials
这是Typescript中的示例实现,因此您可以作为启发:
const Login = () => {
// const {
// state,
// dispatch,
// } = initContext();
const onSignIn = (googleUser) => {
const token = googleUser.getAuthResponse().id_token;
console.log(token);
// dispatch({
// type: 'login',
// });
};
const onFail = ({error}) => {
console.log(error);
};
useEffect(() => {
// @ts-expect-error
const { gapi } = window;
gapi.load('auth2', () => {
const auth2 = gapi.auth2.init({
client_id: '...',
});
gapi.signin2.render('signin-button', {
width: 232,
height: 40,
longtitle: true,
onsuccess: onSignIn,
onfailure: onFail,
});
});
}, []);
return (
<div id="signin-button"></div>
);
};
答案 4 :(得分:0)
没有其他答案对我有用。最终有效的方法是使用id而不是class作为div上的标识符。
<div id="g-signin2" />
代替
<div className="g-signin2" />
除了使用window.gapi.signin2.render
作为其他答案以外。
答案 5 :(得分:0)
可能有点晚了,但我想分享我的实施过程。 就我而言,我想完全自定义按钮,并且还想拥有某种加载程序。我使用钩子重新实现了这个
/* 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 登录,也可以使用