Saber2pr's Blog

useLoadScript

Load js on demand:

import { useEffect, useRef, useState } from 'react'

type Cache = {
  dom: HTMLScriptElement
  lib: any
}

const map = new Map<string, Cache>()

export const useLoadScript = <T>(
  name: string,
  src: string,
  deps: any[] = []
): [T, boolean] => {
  const ref = useRef<T>()
  const [loading, setLoading] = useState(true)

  const loadLib = () => {
    const cache = map.get(name) || ({} as Cache)
    cache.lib = window[name]
    map.set(name, cache)
    ref.current = cache.lib
    setLoading(false)
  }

  useEffect(() => {
    const cache = map.get(name) || ({} as Cache)

    if (cache.lib) {
      ref.current = cache.lib
      setLoading(false)
      return
    }

    if (cache.dom) {
      cache.dom.addEventListener('load', loadLib)
      return () => cache.dom.removeEventListener('load', loadLib)
    }

    const script = document.createElement('script')
    script.src = src
    script.type = 'text/javascript'
    script.crossOrigin = 'true'

    script.addEventListener('load', loadLib)
    document.body.append(script)

    cache.dom = script
    map.set(name, cache)

    return () => script.removeEventListener('load', loadLib)
  }, deps)
  return [ref.current, loading]
}

Use:

const [Hls, loading] = useLoadScript<Hls>(
  'Hls',
  'https://cdn.jsdelivr.net/npm/hls.js@alpha'
)