I am trying to integrate a legacy third-party library that doesn't have an NPM package and only provides a CDN link. I tried adding the script tag directly into my component's JSX, but it keeps throwing errors or simply doesn't load the global variable. Should I be placing this in the index.html file, or is there a way to dynamically inject the script using a React hook like useEffect? I really need to access the library’s functions without breaking the build process or causing memory leaks.
3 answers
The most straightforward "human" approach is to place the <script> tag inside the <head> or at the end of the <body> in your public/index.html file. This ensures the library loads before React initializes. Once loaded, the library usually attaches itself to the global window object. Inside your React component, you can access it using window.LibraryName. If you are using TypeScript, you'll need to declare the variable to avoid "property does not exist" errors. For a more modern approach, you can write a custom hook that creates a document.createElement('script'), sets the src, and appends it to the document, allowing you to track when the script is fully loaded before trying to use it.
If you put the script in index.html, are you running into issues where the component tries to call the library functions before the external network request has actually finished downloading the script?
You can also use a library like react-load-script which handles all the boilerplate for you. It’s much cleaner than manually touching the DOM in your components.
I agree with Sarah. While doing it manually is a good learning exercise, using an established package for script loading handles edge cases like script removal on component unmount, which prevents memory leaks in larger applications.
That is a classic race condition, Gary. To solve this, I usually recommend using the onload event listener on the script tag if you're injecting it dynamically. In React, you can manage this with a state variable called isLoaded. You set it to true inside the onload callback, and then use a useEffect that dependencies on isLoaded to trigger your library-specific logic. This prevents the "undefined" errors that happen when the React lifecycle moves faster than your CDN provider's response time.