1

I am trying to load a script in React rather than bind it in the HTML file. I'm close by can't quite make it work.

My html file:

<!DOCTYPE html>
<html lang="en">
    <head>

        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="google-signin-client_id" content= "817677528939-dss5sreclldv1inb26tb3tueac98d24r.apps.googleusercontent.com">

        <meta name="google-signin-scope" content="profile email">
        <script src="https://apis.google.com/js/platform.js"></script>
        <title>React App</title>
    </head>
    <body>

        <div id="root"></div>
    </body>
</html>

This works. But I'm trying to get it to work without having it in the HTML file.

loadScript.js

const loadScript = (url) => new Promise((resolve, reject) => {
  let ready = false;
  if (!document) {
    reject(new Error('Document was not defined'));
  }
  const tag = document.getElementsByTagName('script')[0];
  const script = document.createElement('script');

  script.type = 'text/javascript';
  script.src = url;
  script.async = true;
  script.onreadystatechange = () => {
    if (!ready && (!this.readyState || this.readyState === 'complete')) {
      ready = true;
      resolve(script);
    }
  };
  script.onload = script.onreadystatechange;

  script.onerror = (msg) => {
    console.log(msg);
    reject(new Error('Error loading script.'));
  };

  script.onabort = (msg) => {
    console.log(msg);
    reject(new Error('Script loading aboirted.'));
  };

  if (tag.parentNode != null) {
    tag.parentNode.insertBefore(script, tag);
  }
});


export default loadScript;

Then in my App.js

loadScript() {
// Load the google maps api script when the component is mounted.

    loadScript("https://apis.google.com/js/platform.js")
        .then((script) => {
        // Grab the script object in case it is ever needed.
            this.script = script;
            this.setState({ apiLoaded: true });
        })
        .catch((err: Error) => {
            console.error(err.message);
        });
}


componentDidMount() {
        console.log('component did mount')

        this.loadScript()

        ///how do I make this gapi below reference gapi inside this.script?
        gapi.load('auth2', () => {
            var auth2 = gapi.auth2.init({
                client_id: '817677528939-dss5sreclldv1inb26tb3tueac98d24r.apps.googleusercontent.com',
                scope: 'profile email',

            })
            .then((auth2) => {
                if (auth2.isSignedIn.get()) {
                    this.setState({
                        redirect:true,
                        gapiLoaded:true
                    })
                } else {
                    console.log( "signed in: " + auth2.isSignedIn.get())
                    this.setState({
                        gapiLoaded: true
                    },
                    () => {console.log('state set')})    
                }

            });
        });
    }

printing gapi

{platform: {…}, _pl: true, additnow: {…}, backdrop: {…}, load: ƒ, …}

printing response

<script type="text/javascript" src="https://apis.google.com/js/platform.js" async="" gapi_processed="true"></script>

It looks like it is printing out the element. How do I then access gapi inside of it?

2
  • Do you have an example of a React component which uses the loadScript? Do you run it in componentDidMount? Commented Nov 24, 2017 at 17:34
  • updated! let me know if you have any more questions Commented Nov 24, 2017 at 17:38

1 Answer 1

1

I think you want to use gapi when it is available. You could shuffle the code around. You wait until it has been loaded using the loadScript.

App.js - React component

loadScript(){
  loadScript("https://apis.google.com/js/platform.js")
    .then((script) => {
      /* setState stuff */
      this.gapiLoad(); // use gapi api, it is now available
    })
}

gapiLoad(){
  window.gapi.load('auth2', () => {
    /* your code */
  })
}

componentDidMount(){
  this.loadScript();
}

Alternatively you could also use the life-cycle componentDidUpdate and test that apiLoaded is true and gapiLoad is false. Then use the gapi api.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.