# react-async-script

> A composition mixin for loading scripts asynchronously for React

Latest version **1.2.0** (published 2020-06-22) · MIT license · 0 weekly downloads

## Install

```sh
npm install react-async-script
pnpm add react-async-script
yarn add react-async-script
bun add react-async-script
```

## Health

**Score 28/100 (F)** — status: abandoned.

Positive: has types package; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.2.0 |
| Published | 2020-06-22 |
| First published | 2015-04-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | separate (@types/react-async-script) |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 41.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 177 |
| Author | Hugo Dozois |
| Maintainers | dozoisch |
| Keywords | react, asynchronous, script-loader |

## Links

- npm: https://www.npmjs.com/package/react-async-script
- Repository: https://github.com/dozoisch/react-async-script
- Issues: https://github.com/dozoisch/react-async-script/issues
- npm.io page: https://npm.io/package/react-async-script

## Dependencies (2)

- [prop-types](https://npm.io/package/prop-types.md) ^15.5.0
- [hoist-non-react-statics](https://npm.io/package/hoist-non-react-statics.md) ^3.3.0

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.2.0 (latest) — 2020-06-22
- 1.1.1 — 2019-07-14
- 1.1.0 — 2019-07-14
- 1.0.1 — 2019-04-08
- 1.0.0 — 2018-08-18
- 1.0.0-rc.1 — 2018-08-13
- 0.11.1 — 2018-08-04
- 0.11.0 — 2018-07-29
- 0.10.0 — 2018-07-24
- 0.9.1 — 2017-04-20
- 0.9.0 — 2017-04-16
- 0.8.0 — 2017-03-24
- 0.7.0 — 2017-03-05
- 0.6.0 — 2016-06-02
- 0.5.1 — 2016-01-15
- … 10 more at https://npm.io/package/react-async-script/versions

## README

# React Async Script Loader

[![Build Status][travis.img]][travis.url] [![npm version][npm.img]][npm.url] [![npm downloads][npm.dl.img]][npm.dl.url] [![Dependencies][deps.img]][deps.url]

**NOTE* - These are the docs for the upcoming `1.0.0` release - for `v0.11.1` documention go to tag here: [0.11.1](https://github.com/dozoisch/react-async-script/tree/v0.11.1)

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.

## Usage

#### Async Script HOC api

`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 as `data-` 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 on `window` for you.
    - `globalName`: *string* : Can provide the name of the global that the script attaches to `window`. Async-script will pass this as a prop to the wrapped component. *(`props[globalName] = window[globalName]`)*
    - `removeOnUnmount`: *boolean* **default=false** : If set to `true` removes the script tag when component unmounts.
    - `scriptId`: *string* : If set, it adds the following id on the script tag.

#### HOC Component props
```js
const AsyncScriptComponent = makeAsyncScriptLoader(URL)(Component);
// ---
<AsyncScriptComponent asyncScriptOnLoad={callAfterScriptLoads} />
```
- `asyncScriptOnLoad`: *function* : called after script finishes loading. *using `script.onload`*


#### Ref and forwardRef

`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:
```js
const AsyncHoc = makeAsyncScriptLoader(URL)(ComponentNeedsScript);

class DisplayComponent extends React.Component {
  constructor(props) {
    super(props);
    this._internalRef = React.createRef();
  }
  componentDidMount() {
    console.log("ComponentNeedsScript's Instance -", this._internalRef.current);
  }
  render() { return (<AsyncHoc ref={this._internalRef} />)}
}
```

##### Notes on Requirements

At least `React@16.4.1` is required due to `forwardRef` usage internally.


### Example

See https://github.com/dozoisch/react-google-recaptcha

```js
// recaptcha.js
export class ReCAPTCHA extends React.Component {
  componentDidUpdate(prevProps) {
    // recaptcha has loaded via async script
    if (!prevProps.grecaptcha && this.props.grecaptcha) {
      this.props.grecaptcha.render(this._container)
    }
  }
  render() { return (
    <div ref={(r) => this._container = r} />)
  }
}

// recaptcha-wrapper.js
import makeAsyncScriptLoader from "react-async-script";
import { ReCAPTCHA } from "./recaptcha";

const callbackName = "onloadcallback";
const URL = `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.grecaptcha
const globalName = "grecaptcha";

export default makeAsyncScriptLoader(URL, {
  callbackName: callbackName,
  globalName: globalName,
})(ReCAPTCHA);

// main.js
import ReCAPTCHAWrapper from "./recaptcha-wrapper.js"

const onLoad = () => console.log("script loaded")

React.render(
  <ReCAPTCHAWrapper asyncScriptOnLoad={onLoad} />,
  document.body
);
```

## Migration to 1.0

- Component is now passed as a second function call
- removeOnMount is now removeOnUnmount (typo fixed!)
- exposeFuncs is no longer needed as it's done automatically!

```diff
-export default makeAsyncScriptLoader(ReCAPTCHA, getURL, {
+export default makeAsyncScriptLoader(getURL, {
   callbackName,
   globalName,
-  removeOnMount: initialOptions.removeOnMount || false,
+  removeOnUnmount: initialOptions.removeOnUnmount || false,
-  exposeFuncs: ["getValue", "getWidgetId", "reset", "execute"],
-});
+})(ReCAPTCHA);
```


## Notes

Pre `1.0.0` and - `React < React@16.4.1` support details in [0.11.1](https://github.com/dozoisch/react-async-script/tree/v0.11.1).

---

[travis.img]: https://travis-ci.org/dozoisch/react-async-script.svg?branch=master
[travis.url]: https://travis-ci.org/dozoisch/react-async-script
[npm.img]: https://badge.fury.io/js/react-async-script.svg
[npm.url]: http://badge.fury.io/js/react-async-script
[npm.dl.img]: https://img.shields.io/npm/dm/react-async-script.svg
[npm.dl.url]: https://www.npmjs.com/package/react-async-script
[deps.img]: https://david-dm.org/dozoisch/react-async-script.svg
[deps.url]: https://david-dm.org/dozoisch/react-async-script

---
_Source: https://npm.io/package/react-async-script · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
