I want to add some external scripts to my ReactJS/TS app and I would like to add these scripts not into index.html but with another component.
if (root) {
createRoot(root).render(
<>
<Scripts />
<BrowserRouter>
<Routes>
<Route path="/" element={<PageWrapper />}>
<Route index element={<UserEdit />} />
<Route path="user/edit" element={<UserEdit />} />
<Route path="user/:id" element={<UserPage />} />
<Route path="*" element={<NoPage />} />
</Route>
</Routes>
</BrowserRouter>
</>
)
}
this is how I would like code to look. Scripts component looks like this:
const Scripts = () => {
const scripts: Scripts = ["frontend/js_clean/check.js","frontend/js_clean/user.js"...]
return ({scripts.map(script => <script key={script} type="text/javascript" src={`${process.env.ASSETS_CDN}/${script}`}></script>)})
}
But the problem is that components which go after Scripts component using variables and functions from external scripts and when I try to start app it gives me an error like:
TypeError: window.isJsonString is not a function
window.isJsonString is declared into frontend/js_clean/user.js script which I try to include into Scripts component. So I am wondering if there is another way to add external scripts to the project without hardcoding it into index.html.
Thanks in advance!
2
Answers
React is all about transforming state (in broad sense) into UI. So, if you are loading something else, you must express it in terms of state.
For your particular task, set a state variable that will indicate if scripts are loaded or not. It will have three possible values: "not loaded", "loaded", "error". Attach
onLoad
andonError
handlers you your script elements and change this state accordingly.What you are doing will not work, because you are adding
<script>
tags to work with JSX. There is no React doc that mentions they handle these tags.Infact, we can be sure that it does not download the scripts, let alone execute them. Here is a Demo, where I have added a single script tag in
JSX
and it did not work.What we have to realise is that what we return from inside React function component is not HTML, but JSX. That JSX is converted to DOM elements by React, and if we include a
<script>
tag it will only work if React handles it. That does not happen right now.Infact, it is a feature that will soon be introduced in react. Right now in canary.
Until then, if you don’t want to include your scripts in
index.html
, you have two options:index.js
, orBoth approaches require you to do some DOM manipulation. What you want to do is create a
script
element and update its attributes and append it to the DOM.There is a hook already for that.
useScript
It lazy loads the script when the component using it is invoked. But the DOM manipulations in the source code is what you also can use to add script tags to the HTML.Here is a super minified version which handles multiple scripts: