9

This is essentially the same question as Using google sign in button with react but the accepted answer does not solve it in my case.

I have a react component:

var LoginButton = React.createClass({

onSignIn: function(googleUser) {
  console.error(" user signed in");                                                                                                                                                               
},

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

render: function() {
  return (
     <div className="g-signin2"/>
  );
}
}

But while the sign-in works successfully, the onSignIn function is never called. In fact none of the options I specify for rendering the custom signin button are present (i.e. the square shape and dark theme), so I guess it's rendering a default button because of the <div>'s class.

I'm currently loading the library synchronously because otherwise gapi is not in scope when componentDidMount is triggered.

The other option I see would be google's recommendation of using <script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script> and wrapping my render in a function. But then either this script has to be loaded inside the component, or else I have to find a way that this function is in scope to be passed as a callback in index.html, neither of which seem like a good solution.

How can I get the custom login button to be rendered instead of the default one?

Community
  • 1
  • 1
amn41
  • 1,164
  • 1
  • 9
  • 17
  • This video explains Google, facebook and linked In login with reactjs https://youtu.be/9MhLHkf7Ifs. It might help someone :-) – Prem Aug 04 '17 at 14:17

2 Answers2

13

This hack does the trick for now...

In my index.html I trigger a custom event when the library loads:

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

and my react component now looks like this :

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 id="my-signin2"></div>
    );
  }

});

note that the rendered <div> has "my-signin2" as an id not a class.

amn41
  • 1,164
  • 1
  • 9
  • 17
  • 1
    This is useful when you need to land in pages rendered by React directly. Thanks. – Xiaofan Hu Jan 05 '16 at 08:58
  • I tried exactly the way you mentioned, but I get error as `'gapi' is not defined`. My code is available at https://github.com/hhimanshu/google-login-with-react, could you help me understand where I am making mistake? – daydreamer May 03 '17 at 04:25
6

I've used JQuery, to load the script via the componentDidMount method...

componentDidMount: function() {
    $.getScript('https://apis.google.com/js/platform.js')
        .done(() => {
            // execute any gapi calls here...
            gapi.signin2.render('g-signin2', {
                // ... options here ...
            });
        });
},

As f13ts said, the rendered <div> should have "my-signin2" as an id, as opposed to a class.

Daniel
  • 61
  • 1
  • 1