Skip to content

Instantly share code, notes, and snippets.

@addisonschultz
Last active October 28, 2023 10:02
Show Gist options
  • Save addisonschultz/1811e75b498311211a7f6b8634fb27cd to your computer and use it in GitHub Desktop.
Save addisonschultz/1811e75b498311211a7f6b8634fb27cd to your computer and use it in GitHub Desktop.
A React hook that lets you add script tags to a component. Useful when needing to load scripts for components in Framer X.
import * as React from "react"
import { useState, useEffect } from "react"
// Hook
let cachedScripts = []
export function useScript(src) {
// Keeping track of script loaded and error state
const [state, setState] = useState({
loaded: false,
error: false,
})
useEffect(() => {
// If cachedScripts array already includes src that means another instance ...
// ... of this hook already loaded this script, so no need to load again.
if (cachedScripts.includes(src)) {
setState({
loaded: true,
error: false,
})
} else {
cachedScripts.push(src)
// Create script
let script = document.createElement("script")
script.src = src
script.async = true
// Script event listener callbacks for load and error
const onScriptLoad = () => {
setState({
loaded: true,
error: false,
})
}
const onScriptError = () => {
// Remove from cachedScripts we can try loading again
const index = cachedScripts.indexOf(src)
if (index >= 0) cachedScripts.splice(index, 1)
script.remove()
setState({
loaded: true,
error: true,
})
}
script.addEventListener("load", onScriptLoad)
script.addEventListener("error", onScriptError)
// Add script to document body
document.body.appendChild(script)
// Remove event listeners on cleanup
return () => {
script.removeEventListener("load", onScriptLoad)
script.removeEventListener("error", onScriptError)
}
}
}, [src]) // Only re-run effect if script src changes
return [state.loaded, state.error]
}
@addisonschultz
Copy link
Author

addisonschultz commented Aug 18, 2020

@AndrewTraub I would suggest using it in the useEffect from the example above. It returns a boolean if it's loaded, and if so, you can then do what you'd like from there.

@ridhwaans
Copy link

what if the script exists as a project file and not a url? how would you modify the hook?

@addisonschultz
Copy link
Author

addisonschultz commented Oct 29, 2020

@ridhwaans I have a Framer Example that lets you choose either a URL or a local file using a property control in the component itself :)

You can see how it's set up here: https://github.com/framer/framer-bridge-stencil-kit/tree/master/code/utils

You can look into constants.tsx to see the actual util

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment