Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jcoreio/react-render-props-script-loader

an easier to use React dynamic script loader with a render prop and SSR
https://github.com/jcoreio/react-render-props-script-loader

dynamic-script loader react script script-tag

Last synced: 27 days ago
JSON representation

an easier to use React dynamic script loader with a render prop and SSR

Awesome Lists containing this project

README

        

# react-render-props-script-loader

[![CircleCI](https://circleci.com/gh/jcoreio/react-render-props-script-loader.svg?style=svg)](https://circleci.com/gh/jcoreio/react-render-props-script-loader)
[![Coverage Status](https://codecov.io/gh/jcoreio/react-render-props-script-loader/branch/master/graph/badge.svg)](https://codecov.io/gh/jcoreio/react-render-props-script-loader)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![npm version](https://badge.fury.io/js/react-library-skeleton.svg)](https://badge.fury.io/js/react-library-skeleton)

an easier to use dynamic script loader with a [render prop](https://reactjs.org/docs/render-props.html)
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 `` component,
it will create the script tag you've requested.

`` doesn't load a given script URL more than once, even if there
is a pre-existing `` 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 of `package.json`, you will probably need to add a rule to
transpile this package.

# Installation

```sh
npm install --save react-render-props-script-loader
```

# Example

```js
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} />
}}

)
```

# API

## `useScript(props: Props)`

```js
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:

```ts
type State = {
loading: boolean
loaded: boolean
error: ?Error
promise: ?Promise
}
```

## `ScriptLoader`

```js
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:

```js
{
loading: boolean,
loaded: boolean,
error: ?Error,
promise: ?Promise,
}
```

## Server-Side Rendering

```js
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:

```js
const registry = new ScriptsRegistry()

const body = ReactDOM.renderToString(



)
```

Then render `registry.scriptTags()` in your head element:

```js
const html = (


...
{registry.scriptTags()}

...

)
```

## Content Security Policy

Make sure your header includes this meta tag:

```jsx

```

And in SSR, pass the `nonce` to `registry.scriptTags({ nonce })`.