useState()
hook to create a state variable for the load status of the script.useEffect()
hook to handle all the logic for loading and unloading the script anytime the src
changes.src
value is present, set the status
to 'idle'
and return.Document.querySelector()
to check if a <script>
element with the appropriate src
value exists.Document.createElement()
to create one and give it the appropriate attributes.data-status
attribute as a way to indicate the status of the script, setting it to 'loading'
initially.status
from its data-status
attribute. This ensures that no duplicate element will be created.EventTarget.addEventListener()
to listen for 'load'
and 'error'
events and handle them by updating the data-status
attribute and the status
state variable.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) { setStatus('idle'); return; } let script = document.querySelector(`script[src="${src}"]`); if (!script) { script = document.createElement('script'); script.src = src; script.async = true; script.setAttribute('data-status', 'loading'); document.body.appendChild(script); const setDataStatus = event => { script.setAttribute( 'data-status', event.type === 'load' ? 'ready' : 'error' ); }; script.addEventListener('load', setDataStatus); script.addEventListener('error', setDataStatus); } else { setStatus(script.getAttribute('data-status')); } 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 =
'data:text/plain;charset=utf-8;base64,KGZ1bmN0aW9uKCl7IGNvbnNvbGUubG9nKCdIZWxsbycpIH0pKCk7';
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'));
Subscribe to get resources directly to your inbox. You won't receive any spam! ✌️