# React Async Script Loader [![Build Status][travis.img]][travis.url] [![npm version][npm.img]][npm.url] [![npm downloads][npm.dl.img]][npm.dl.url] [![Dependencies][deps.img]][deps.url] **NOTE* - These are the docs for the upcoming `1.0.0` release - for `v0.11.1` documention go to tag here: [0.11.1](https://github.com/dozoisch/react-async-script/tree/v0.11.1) A React HOC for loading 3rd party scripts asynchronously. This HOC allows you to wrap a component that needs 3rd party resources, like reCAPTCHA or Google Maps, and have them load the script asynchronously. ## Usage #### Async Script HOC api `makeAsyncScriptLoader(getScriptUrl, options)(Component)` - `Component`: The *Component* to wrap. - `getScriptUrl`: *string* or *function* that returns the full URL of the script tag. - `options` *(optional)*: - `attributes`: *object* : If the script needs attributes (such as `data-` attributes), then provide them as key/value pairs of strings and they will be added to the generated script tag. - `callbackName`: *string* : If the script needs to call a global function when finished loading *(for example: `recaptcha/api.js?onload=callbackName`)*. Please provide the callback name here and it will be autoregistered on `window` for you. - `globalName`: *string* : Can provide the name of the global that the script attaches to `window`. Async-script will pass this as a prop to the wrapped component. *(`props[globalName] = window[globalName]`)* - `removeOnUnmount`: *boolean* **default=false** : If set to `true` removes the script tag when component unmounts. - `scriptId`: *string* : If set, it adds the following id on the script tag. #### HOC Component props ```js const AsyncScriptComponent = makeAsyncScriptLoader(URL)(Component); // --- ``` - `asyncScriptOnLoad`: *function* : called after script finishes loading. *using `script.onload`* #### Ref and forwardRef `react-async-script` uses react's `forwardRef` method to pass along the `ref` applied to the wrapped component. If you pass a `ref` prop you'll have access to your wrapped components instance. See the tests for detailed example. Simple Example: ```js const AsyncHoc = makeAsyncScriptLoader(URL)(ComponentNeedsScript); class DisplayComponent extends React.Component { constructor(props) { super(props); this._internalRef = React.createRef(); } componentDidMount() { console.log("ComponentNeedsScript's Instance -", this._internalRef.current); } render() { return ()} } ``` ##### Notes on Requirements At least `React@16.4.1` is required due to `forwardRef` usage internally. ### Example See https://github.com/dozoisch/react-google-recaptcha ```js // recaptcha.js export class ReCAPTCHA extends React.Component { componentDidUpdate(prevProps) { // recaptcha has loaded via async script if (!prevProps.grecaptcha && this.props.grecaptcha) { this.props.grecaptcha.render(this._container) } } render() { return (
this._container = r} />) } } // recaptcha-wrapper.js import makeAsyncScriptLoader from "react-async-script"; import { ReCAPTCHA } from "./recaptcha"; const callbackName = "onloadcallback"; const URL = `https://www.google.com/recaptcha/api.js?onload=${callbackName}&render=explicit`; // the name of the global that recaptcha/api.js sets on window ie: window.grecaptcha const globalName = "grecaptcha"; export default makeAsyncScriptLoader(URL, { callbackName: callbackName, globalName: globalName, })(ReCAPTCHA); // main.js import ReCAPTCHAWrapper from "./recaptcha-wrapper.js" const onLoad = () => console.log("script loaded") React.render( , document.body ); ``` ## Migration to 1.0 - Component is now passed as a second function call - removeOnMount is now removeOnUnmount (typo fixed!) - exposeFuncs is no longer needed as it's done automatically! ```diff -export default makeAsyncScriptLoader(ReCAPTCHA, getURL, { +export default makeAsyncScriptLoader(getURL, { callbackName, globalName, - removeOnMount: initialOptions.removeOnMount || false, + removeOnUnmount: initialOptions.removeOnUnmount || false, - exposeFuncs: ["getValue", "getWidgetId", "reset", "execute"], -}); +})(ReCAPTCHA); ``` ## Notes Pre `1.0.0` and - `React < React@16.4.1` support details in [0.11.1](https://github.com/dozoisch/react-async-script/tree/v0.11.1). --- [travis.img]: https://travis-ci.org/dozoisch/react-async-script.svg?branch=master [travis.url]: https://travis-ci.org/dozoisch/react-async-script [npm.img]: https://badge.fury.io/js/react-async-script.svg [npm.url]: http://badge.fury.io/js/react-async-script [npm.dl.img]: https://img.shields.io/npm/dm/react-async-script.svg [npm.dl.url]: https://www.npmjs.com/package/react-async-script [deps.img]: https://david-dm.org/dozoisch/react-async-script.svg [deps.url]: https://david-dm.org/dozoisch/react-async-script