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.
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 asdata-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 onwindowfor you.globalName: string : Can provide the name of the global that the script attaches towindow. Async-script will pass this as a prop to the wrapped component. (props[globalName] = window[globalName])removeOnUnmount: booleandefault=false : If set totrueremoves the script tag when component unmounts.scriptId: string : If set, it adds the following id on the script tag.
constAsyncScriptComponent=makeAsyncScriptLoader(URL)(Component);// ---<AsyncScriptComponentasyncScriptOnLoad={callAfterScriptLoads}/>asyncScriptOnLoad: function : called after script finishes loading. usingscript.onload
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:
constAsyncHoc=makeAsyncScriptLoader(URL)(ComponentNeedsScript);classDisplayComponentextendsReact.Component{constructor(props){super(props);this._internalRef=React.createRef();}componentDidMount(){console.log("ComponentNeedsScript's Instance -",this._internalRef.current);}render(){return(<AsyncHocref={this._internalRef}/>)}}At least [email protected] is required due to forwardRef usage internally.
See https://github.com/dozoisch/react-google-recaptcha
// recaptcha.jsexportclassReCAPTCHAextendsReact.Component{componentDidUpdate(prevProps){// recaptcha has loaded via async scriptif(!prevProps.grecaptcha&&this.props.grecaptcha){this.props.grecaptcha.render(this._container)}}render(){return(<divref={(r)=>this._container=r}/>)}}// recaptcha-wrapper.jsimportmakeAsyncScriptLoaderfrom"react-async-script";import{ReCAPTCHA}from"./recaptcha";constcallbackName="onloadcallback";constURL=`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.grecaptchaconstglobalName="grecaptcha";exportdefaultmakeAsyncScriptLoader(URL,{callbackName: callbackName,globalName: globalName,})(ReCAPTCHA);// main.jsimportReCAPTCHAWrapperfrom"./recaptcha-wrapper.js"constonLoad=()=>console.log("script loaded")React.render(<ReCAPTCHAWrapperasyncScriptOnLoad={onLoad}/>,document.body);