Search code examples
reactjsreact-hooksgoogle-api-js-client

Converting a class based component to hooks (gapi API)


I have this class based component using the gapi (Google Auth) API that renders a button and it works:

import React from 'react';

class GoogleAuth extends React.Component {
  state = { isSignedIn: null };

  componentDidMount() {
    window.gapi.load('client:auth2', () => {
      window.gapi.client
        .init({
          clientId: process.env.REACT_APP_CLIENT_ID,
          scope: 'email',
        })
        .then(() => {
          this.auth = window.gapi.auth2.getAuthInstance();
          this.handleAuthChange();
          this.auth.isSignedIn.listen(this.handleAuthChange);
        });
    });
  }

  handleAuthChange = () => {
    this.setState({ isSignedIn: this.auth.isSignedIn.get() });
  };

  handleSignIn = () => {
    this.auth.signIn();
  };

  handleSignOut = () => {
    this.auth.signOut();
  };

  renderAuthButton() {
    if (this.state.isSignedIn === null) {
      return null;
    } else if (this.state.isSignedIn) {
      return <button onClick={this.handleSignOut}>Sign Out</button>;
    } else {
      return <button onClick={this.handleSignIn}>Sign in with Google</button>;
    }
  }

  render() {
    return <div>{this.renderAuthButton()}</div>;
  }
}

export default GoogleAuth;

I'm having a tough time trying to convert this to use hooks. The main issue is this.auth... That's how the class has a reference to window.gapi.auth2.getAuthInstance()

I have tried many different ways including keeping auth in state like:

export default function GoogleAuth() {
    const [isSignedIn, setIsSignedIn] = useState(null);
    const [auth, setAuth] = useState(null);
    useEffect(() => {
        window.gapi.load('client:auth2', () => {
            window.gapi.client
                .init({
                    clientId: process.env.REACT_APP_CLIENT_ID,
                    scope: 'email',
                })
                .then(() => {
                    setAuth(window.gapi.auth2.getAuthInstance());
                    setIsSignedIn(auth.isSignedIn.get());
                    auth.isSignedIn.listen(() => setIsSignedIn(auth.isSignedIn.get()));
                });
        });
    }, [auth]);

Solution

  • It's only 8 months later but try useRef with auth like below. It works for me.

       const GoogleAuth  = () => {
          const [isSignedIn, setSignedIn] = useState(null)
          const auth = useRef(null);
          useEffect(() => {
            window.gapi.load('client:auth2', () => {
              window.gapi.client.init({
                clientId:
                  'jcu.apps.googleusercontent.com',
                scope: 'email'
              }).then(() => {
                auth.current = window.gapi.auth2.getAuthInstance();
                setSignedIn(auth.current.isSignedIn.get());
                auth.current.isSignedIn.listen(onAuthChange)
              });
            });
          }, [isSignedIn]);
        
         const onAuthChange = () => {
              setSignedIn(auth.current.isSignedIn.get())
          }
        
         if (isSignedIn === null) {
            return (
              <div>I don't know if we are signed in!</div>
            );
          } else if ( isSignedIn ){
            return (
              <div>I am signed in!</div>
            );
          } else {
            return ( <div>I am not signed in. :(</div>);
          }
        }