React Async Script Loader

1.2.0 · active · verified Sun Apr 19

react-async-script is a lightweight React Higher-Order Component (HOC) designed to facilitate the asynchronous loading of external third-party JavaScript scripts within React applications. It is particularly useful for integrating services like Google reCAPTCHA, Google Maps, or other widgets where scripts need to be loaded dynamically without blocking the main thread. The current stable version is 1.2.0, building upon the significant 1.0.0 rewrite that introduced modern React features. The library supports customizing script attributes, automatically registering global callback functions (e.g., for `onload` events), and exposing global variables created by the loaded scripts as props to the wrapped component. It also incorporates React's `forwardRef` for proper ref handling, requiring React version 16.4.1 or higher. While no explicit release cadence is stated, it receives updates to address issues and maintain compatibility with React. Its key differentiator is its focused approach as a simple HOC for script management.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates how to use `makeAsyncScriptLoader` to load an external script (e.g., Google Maps API), handle its `onload` callback, access global variables exposed by the script, and utilize `forwardRef` with the wrapped component. Replace `YOUR_API_KEY` with an actual key.

import React from 'react';
import ReactDOM from 'react-dom';
import makeAsyncScriptLoader from 'react-async-script';

// A placeholder component that would typically consume the loaded script
class MyComponentNeedingScript extends React.Component {
  componentDidUpdate(prevProps) {
    // Access the global object exposed by the loaded script via props
    if (!prevProps.googleMaps && this.props.googleMaps) {
      console.log('Google Maps API is available:', this.props.googleMaps);
      // Example: Initialize a map once the API is loaded
      // new this.props.googleMaps.Map(document.getElementById('map'), { center: {lat: -34, lng: 151}, zoom: 8 });
    }
  }
  render() {
    return (
      <div>
        <p>Loading external script...</p>
        {/* You might render a placeholder or a loading spinner here */}
        <div id="map" style={{ width: '100%', height: '300px' }}></div>
      </div>
    );
  }
}

// Define the script URL, callback name, and the global object name
const SCRIPT_URL = `https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap`;
const CALLBACK_NAME = 'initMap';
const GLOBAL_NAME = 'googleMaps'; // The global object set by the script (e.g., window.googleMaps)

// Wrap your component with the HOC
const GoogleMapsLoader = makeAsyncScriptLoader(SCRIPT_URL, {
  callbackName: CALLBACK_NAME,
  globalName: GLOBAL_NAME,
  removeOnUnmount: true, // Optional: remove script tag when component unmounts
})(MyComponentNeedingScript);

class App extends React.Component {
  constructor(props) {
    super(props);
    this._myRef = React.createRef();
  }

  componentDidMount() {
    console.log("Ref to MyComponentNeedingScript instance:", this._myRef.current);
  }

  handleScriptLoad = () => {
    console.log("External Google Maps script has finished loading!");
    // Any post-load actions can be performed here
  };

  render() {
    return (
      <div>
        <h1>React Async Script Loader with Google Maps</h1>
        <GoogleMapsLoader ref={this._myRef} asyncScriptOnLoad={this.handleScriptLoad} />
      </div>
    );
  }
}

// Ensure a root element exists for React to render into
const rootElement = document.getElementById('root');
if (!rootElement) {
  const div = document.createElement('div');
  div.id = 'root';
  document.body.appendChild(div);
}

ReactDOM.render(<App />, rootElement);

// Simulate the global callback function that the Google Maps API calls
// This must be a global function for the script to find it
window[CALLBACK_NAME] = () => {
  console.log(`Global callback '${CALLBACK_NAME}' executed.`);
  // For Google Maps, the 'google.maps' global becomes available after this.
  // The HOC will pick this up and pass 'googleMaps' as a prop.
};

view raw JSON →