Skip to content

Instantly share code, notes, and snippets.

@wichopy
Created December 2, 2019 18:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wichopy/901b657af7f735627db4c918bc2ee3a0 to your computer and use it in GitHub Desktop.
Save wichopy/901b657af7f735627db4c918bc2ee3a0 to your computer and use it in GitHub Desktop.
A generic script loader class for loading external scripts in React
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