UNPKG

@massds/mayflower-react

Version:

React versions of Mayflower design system UI components

63 lines (58 loc) 2.26 kB
import React from "react"; const useScript = src => { // Keep track of script status ("idle", "loading", "ready", "error") const _React$useState = React.useState(src ? 'loading' : 'idle'), status = _React$useState[0], setStatus = _React$useState[1]; React.useEffect(() => { // Allow falsy src value if waiting on other data needed for // constructing the script URL passed to this hook. if (!src) { setStatus('idle'); return; } // Fetch existing script element by src // It may have been added by another intance of this hook let script = document.querySelector("script[src=\"" + src + "\"]"); if (!script) { // Create script script = document.createElement('script'); script.src = src; script.async = true; script.defer = true; script.setAttribute('data-status', 'loading'); // Add script to document body document.body.appendChild(script); // Store status in attribute on script // This can be read by other instances of this hook const setAttributeFromEvent = event => { script.setAttribute('data-status', event.type === 'load' ? 'ready' : 'error'); }; script.addEventListener('load', setAttributeFromEvent); script.addEventListener('error', setAttributeFromEvent); } else { // Grab existing script status from attribute and set to state. setStatus(script.getAttribute('data-status')); } // Script event handler to update status in state // Note: Even if the script already exists we still need to add // event handlers to update the state for *this* hook instance. const setStateFromEvent = event => { setStatus(event.type === 'load' ? 'ready' : 'error'); }; // Add event listeners script.addEventListener('load', setStateFromEvent); script.addEventListener('error', setStateFromEvent); // Remove event listeners on cleanup // eslint-disable-next-line consistent-return return () => { if (script) { script.removeEventListener('load', setStateFromEvent); script.removeEventListener('error', setStateFromEvent); script.remove(); } }; }, [src]); return status; }; export default useScript;