React, Hooks, Effect, State, Event

Dynamically loads an external script.

  • Use the useState() hook to create a state variable for the load status of the script.
  • Use the useEffect() hook to handle all the logic for loading and unloading the script anytime the src changes.
  • If no src value is present, set the status to 'idle' and return.
  • Use Document.querySelector() to check if a <script> element with the appropriate src value exists.
  • If no relevant element exists, use Document.createElement() to create one and give it the appropriate attributes.
  • Use the data-status attribute as a way to indicate the status of the script, setting it to 'loading' initially.
  • If a relevant element exists, skip initialization and update the status from its data-status attribute. This ensures that no duplicate element will be created.
  • Use EventTarget.addEventListener() to listen for 'load' and 'error' events and handle them by updating the data-status attribute and the status state variable.
  • Finally, when the component unmounts, use Document.removeEventListener() to remove any listeners bound to the element.
const useScript = src => {
  const [status, setStatus] = React.useState(src ? 'loading' : 'idle');

  React.useEffect(() => {
    if (!src) {

    let script = document.querySelector(`script[src="${src}"]`);

    if (!script) {
      script = document.createElement('script');
      script.src = src;
      script.async = true;
      script.setAttribute('data-status', 'loading');

      const setDataStatus = event => {
          event.type === 'load' ? 'ready' : 'error'
      script.addEventListener('load', setDataStatus);
      script.addEventListener('error', setDataStatus);
    } else {

    const setStateStatus = event => {
      setStatus(event.type === 'load' ? 'ready' : 'error');

    script.addEventListener('load', setStateStatus);
    script.addEventListener('error', setStateStatus);

    return () => {
      if (script) {
        script.removeEventListener('load', setStateStatus);
        script.removeEventListener('error', setStateStatus);
  }, [src]);

  return status;
const script =

const Child = () => {
  const status = useScript(script);
  return <p>Child status: {status}</p>;

const MyApp = () => {
  const status = useScript(script);
  return (
      <p>Parent status: {status}</p>
      <Child />

ReactDOM.render(<MyApp />, document.getElementById('root'));

Recommended snippets

  • useKeyPress

    React, Hooks

    Listens for changes in the pressed state of a given key.

  • useUnload

    React, Hooks

    Handles the beforeunload window event.

  • usePersistedState

    React, Hooks

    Returns a stateful value, persisted in localStorage, and a function to update it.