Created
December 2, 2019 18:36
-
-
Save wichopy/901b657af7f735627db4c918bc2ee3a0 to your computer and use it in GitHub Desktop.
A generic script loader class for loading external scripts in React
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ScriptLoader { | |
constructor() { | |
this.loadedSDKs = []; | |
this.sdks = { | |
stripe: { | |
src: 'https://js.stripe.com/v3/', | |
id: 'stripe-jssdk', | |
globalName: 'Stripe', | |
}, | |
twitter: { | |
src: 'https://platform.twitter.com/widgets.js', | |
id: 'twitter-wjs', | |
globalName: 'twttr', | |
}, | |
// ...etc | |
} | |
this.load = (name) => { | |
if (this.loadedSDKs.includes(name)) { | |
return Promise.resolve(); | |
} | |
const inFlight = this.inflightRequests.get(name); | |
if (inFlight) { | |
return inFlight; | |
} | |
const inflightPromise = new Promise((res, rej) => { | |
// Note: This will break if your HTML does not have at least 1 script tag present. | |
const firstJSTag = document.getElementsByTagName('script')[0]; | |
const sdk = document.createElement('script'); | |
sdk.src = this.sdks[name].src; | |
sdk.async = true; | |
sdk.id = this.sdks[name].id; | |
sdk.onerror = (err) => { | |
rej(err); | |
}; | |
sdk.onload = () => { | |
res(); | |
this.loadedSDKs.push(name); | |
this.inflightRequests.delete(name); | |
}; | |
firstJSTag.parentNode.insertBefore(sdk, firstJSTag); | |
}); | |
this.inflightRequests.set( | |
name, | |
inflightPromise, | |
); | |
return inflightPromise; | |
}; | |
this.isLoaded = (name) => { | |
return this.loadedSDKs.includes(name); | |
}; | |
} | |
} | |
const scriptLoader = new ScriptLoader(); | |
// Singleton, we only want one instance of SDK loader per app. | |
export default scriptLoader; | |
/** | |
Where ever you load your Stripe Provider you can use the ScriptLoader class like so to hook into React. | |
```js | |
import { StripeProvider, Elements } from 'react-stripe-elements'; | |
import ScriptLoader from 'common/scriptloader'; | |
// ... | |
componentDidMount() { | |
if (ScriptLoader.isLoaded('stripe')) { | |
this.props.onLoad(); | |
this.setState({ | |
stripe: window.Stripe(this.props.stripePublicKey), | |
}); | |
} else { | |
ScriptLoader.load('stripe') | |
.then(() => { | |
this.props.onLoad(); | |
this.setState({ | |
stripe: window.Stripe(this.props.stripePublicKey), | |
}); | |
}) | |
.catch((err) => { | |
this.props.onError(); | |
}); | |
} | |
} | |
// ... | |
return <StripeProvider stripe={this.state.stripe}> | |
<Elements> | |
{this.props.children} | |
</Elements> | |
</StripeProvider>; | |
``` | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment