react-render-props-script-loader
v1.4.2
Published
an easier to use dynamic script loader
Downloads
6,139
Maintainers
Readme
react-render-props-script-loader
an easier to use dynamic script loader with a render prop and now a React custom hook.
This is useful if you want to wait to load the Google Maps API until the user
navigates to a view that uses it. When you mount a <ScriptLoader>
component,
it will create the script tag you've requested.
<ScriptLoader>
doesn't load a given script URL more than once, even if there
is a pre-existing <script>
tag for that URL that it didn't create. If src
prop changes, it will load that new URL.
Version notes
- if building for legacy browsers with a bundler like Webpack that supports the
module
field ofpackage.json
, you will probably need to add a rule to transpile this package.
Installation
npm install --save react-render-props-script-loader
Example
import * as React from 'react'
import ScriptLoader from 'react-render-props-script-loader'
import MapView from './MapView'
export const MapViewContainer = (props) => (
<ScriptLoader
type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"
onLoad={() => console.log('loaded google maps!')}
onError={(error) =>
console.error('failed to load google maps:', error.stack)
}
>
{({ loading, error }) => {
if (loading) return <h3>Loading Google Maps API...</h3>
if (error) return <h3>Failed to load Google Maps API: {error.message}</h3>
return <MapView {...props} />
}}
</ScriptLoader>
)
API
useScript(props: Props)
import { useScript } from 'react-render-props-script-loader'
props.src
(required string
)
The script URL.
props.onLoad
(?() => any
)
A callback that ScriptLoader
will call once the script has been loaded
props.onError
(?(error: Error) => any
)
A callback that ScriptLoader
will call if there was an error loading the
script
Returns
A state object of the following type:
type State = {
loading: boolean
loaded: boolean
error: ?Error
promise: ?Promise<any>
}
ScriptLoader
import ScriptLoader from 'react-render-props-script-loader'
src
(required string
)
The script URL.
onLoad
(?() => any
)
A callback that ScriptLoader
will call once the script has been loaded
onError
(?(error: Error) => any
)
A callback that ScriptLoader
will call if there was an error loading the
script
children
(?(state: State) => ?React.Node
)
The render function. It will be called with an object having the following props, and may return your desired content to display:
{
loading: boolean,
loaded: boolean,
error: ?Error,
promise: ?Promise<any>,
}
Server-Side Rendering
import {
ScriptsRegistry,
ScriptsRegistryContext,
} from 'react-render-props-script-loader'
On the server, create an instance of ScriptsRegistry
and put it on the app's
context:
const registry = new ScriptsRegistry()
const body = ReactDOM.renderToString(
<ScriptsRegistryContext.Provider value={registry}>
<App />
</ScriptsRegistryContext.Provider>
)
Then render registry.scriptTags()
in your head element:
const html = (
<html className="default">
<head>
...
{registry.scriptTags()}
</head>
...
</html>
)
Content Security Policy
Make sure your header includes this meta tag:
<meta property="csp-nonce" content={nonce} />
And in SSR, pass the nonce
to registry.scriptTags({ nonce })
.