加载React组件时出现"gapi未定义"错误

18

我正在尝试使用React整合Google登录 (链接)。
我找到了一个以前解决这个问题的问题Using google sign in button with react 2

我复制了相同的步骤。在我的index.html中,我执行以下操作

<script src="https://apis.google.com/js/platform.js?onload=triggerGoogleLoaded" async defer></script>
    <script type="text/javascript">
        function triggerGoogleLoaded() {
            console.log("google event loaded");
            window.dispatchEvent(new Event('google-loaded'));
        }
    </script>

那么我的Component看起来像这样

var LoginButton = React.createClass({

    onSignIn: function(googleUser) {
        console.log("user signed in"); // plus any other logic here
    },

    renderGoogleLoginButton: function() {
        console.log('rendering google signin button');
        gapi.signin2.render('my-signin2', {
            'scope': 'https://www.googleapis.com/auth/plus.login',
            'width': 200,
            'height': 50,
            'longtitle': true,
            'theme': 'light',
            'onsuccess': this.onSignIn
        })
    },

    componentDidMount: function() {
        window.addEventListener('google-loaded',this.renderGoogleLoginButton);
    },

    render: function() {
        let displayText = "Sign in with Google";
        return (
            <div class="g-signin2" data-onsuccess="onSignIn"></div>
        );
    }

});

export default LoginButton;

当我使用yarn start运行程序时,我遇到了

/Users/Harit.Himanshu/bl/sources/webs/google-login/src/LoginButton.js
  11:9   error    'gapi' is not defined                             no-undef
  26:13  warning  'displayText' is assigned a value but never used  no-unused-vars

✖ 2 problems (1 error, 1 warning)

完整的源代码可以在https://github.com/hhimanshu/google-login-with-react找到。

能有人帮我理解我的错误吗?

谢谢

5个回答

25

在我看来,你正在将Google APIs作为脚本标签进行加载,我们期望这会将window.gapi设置为Google API。然而,你随后运行了Eslint或其他检查器,而它根本不知道window.gapi应该存在。它因为看到你使用了未声明的变量而失败。

一种简单的解决方法是告诉Eslint你知道自己在做什么;

/* global gapi */
将此代码放在文件顶部,eslint 将会将 gapi 视为已知全局变量。

在你的文件顶部添加这段代码,eslint 就会把 gapi 当作已知的全局变量。


谢谢@steve,这帮助我得到了按钮,现在我卡在了https://stackoverflow.com/questions/43767485/react-unable-to-perform-google-sign-in-no-errors-are-visible,你知道我哪里错了吗? - daydreamer

5
你也可以尝试使用 gapi-script 这个包,它可以即时提供 gapi,这样你就不必等待任何脚本加载,只需导入并使用即可:
import { gapi } from 'gapi-script';

这不是一个好的解决方案,因为gapi脚本会被Google动态更新,而这只是脚本的硬拷贝。你可能会得到一个过时的脚本版本,导致你的应用程序停止工作。 - jantobola
是的,这是真的,我同意你的观点。我不建议企业和公司使用这个软件包,只适用于小型项目、学习等。 - Lucas Andrade
1
软件包已更新,现在有一个函数可以从谷歌的链接下载并使用真实脚本。 - Lucas Andrade

5

这对我很有帮助。将其放在componentDidMount或constructor中:

componentDidMount() {
    window.gapi.load('auth2', () => {
        // Retrieve the singleton for the GoogleAuth library and set up the client.
        this.auth2 = window.gapi.auth2.init({
            client_id: '436676563344-.apps.googleusercontent.com',
            cookiepolicy: 'single_host_origin',
        });

        this.auth2.attachClickHandler(this.refs.googleButton, {},
            (googleUser) => {
                this.googleLogin(googleUser.getBasicProfile());
            }, (error) => {

            });
    });
}

1
我仍然遇到了OP的错误(“Uncaught ReferenceError:gapi未定义”)。你是否在某个地方定义了gapi? - Rbar
1
你是否将 <script src="https://apis.google.com/js/platform.js?onload=triggerGoogleLoaded" async defer></script> 放在你的脚本之前? - Giang Le
你知道我怎样才能让gapi与react-native一起工作吗? - Bomber
@Bomber 抱歉,但我不知道 :( - Giang Le

2

请确保不要使用async defer,否则会导致window.gapi.someMethod()和您的脚本加载之间出现竞争条件。

简而言之,在您的index.html文件中,从您的脚本标签中删除 async defer

之前的代码:

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

之后

<script src="https://apis.google.com/js/platform.js?onload=triggerGoogleLoaded"></script>

0

我遇到了一个类似的问题。

我在使用 'react-snap' 进行 SEO 时,它阻止了我使用 'gapi'。我发现了 navigator.userAgent 中的 'ReactSnap'。

if (navigator.userAgent !== 'ReactSnap') {
    // some code to dynamically load a script
    let myScript = document.createElement('script')
    myScript.setAttribute('src', 'https://apis.google.com/js/platform.js')
    document.body.appendChild(myScript)
}

我解决了一个问题。 它工作得非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接