I'm converting an HTML theme to Reactjs, I'm having a hard time trying to embed the external Javascript file of that template. I tried appending script to body with useEffect but no success. My problem I think was the function in that Javascript file has executed before DOM render, either way my template is not rendering properly as HTML.
That external script has content of the type:
function(a) {
var b = window.ABC|| {};
b = function() {
function c(c, d) {
var f, e = this;
e.defaults = {
.....
}
var b = 0;
return c
}(),...
I've been searching for days but no results
Edited:
In SingleProduct.js I want images in Product slider work
import React, { useEffect, useLayoutEffect } from 'react';
import RelatedProduct from '../Partials/RelatedProduct';
const SingleProduct = () => {
useLayoutEffect(() => {
document.body.style = 'background: #fff'
}, [])
useEffect(() => {
const script = document.createElement('script')
script.src = '/assets/js/slick-slider.js' // path of the plugin called Slick Slider
script.async = true // false not work too
document.body.append(script) // the element <script> is appended but no work
}, [])
return (
<>
...
The element is appended but no work
The images that should have been in Slider still don't display properly, (they just show up in order)
import '../hooks/slick-slider.min';
One more thing: the external js file plugin can run the first time the website shows up, but when I switch to another route with react-router and come back it doesn't render properly, hard to explain, but I'm sure is that there are many people who have not solved this problem like me.
I have searched and the answers related to the type IIFE function something that does not integrate, but I think there must be a workaround?
The script I'm trying to embed: https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js
I know this plug-in is already on NPM but I would like to try embed it in my website this way and solve my issue.
The easiest way would be to add your scripts directly to your html-head tag (or somewhere else):
<script src="https://code.jquery.com/jquery-3.6.0.min.js" id="external-js"></script>
<script src="https://kenwheeler.github.io/slick/slick/slick.js" id="external-js"></script>
This way, your component can basically be reduced to this:
import React, { useEffect } from "react";
import ReactDOM from "react-dom";
const App = () => {
useEffect(
() => {
const sliderComponent = jQuery(".img-slider");
sliderComponent.slick();
},
[/* run once or add image source dependencies */]
);
return (
<div className="img-slider" style={{ width: 300 }}>
<img src="https://picsum.photos/200" />
<img src="https://picsum.photos/200" />
<img src="https://picsum.photos/200" />
</div>
);
};
ReactDOM.render(<App />, document.getElementById("container"));
Another way would be to add scripts dynamically, as you suggested. Unfortunatelly, this requires a little bit more code on your side, as you need so be sure, the scripts are loaded when you call sliderComponent.slick()
. Out of my head, this could look like the following, heavily borrowed from https://stackoverflow.com/a/14644704/1893976.
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
const scripts = [
"https://code.jquery.com/jquery-3.6.0.min.js",
"https://kenwheeler.github.io/slick/slick/slick.js"
];
// borrowed from Jaykesh Patel, but modified to use Promises
// https://stackoverflow.com/a/14644704/1893976
function loadScript( url ) {
return new Promise((resolve, reject) => {
var script = document.createElement( "script" )
script.type = "text/javascript";
if(script.readyState) { // only required for IE <9
script.onreadystatechange = function() {
if ( script.readyState === "loaded" || script.readyState === "complete" ) {
script.onreadystatechange = null;
resolve();
}
};
} else { //Others
script.onload = function() {
resolve();
};
}
script.src = url;
document.getElementsByTagName( "head" )[0].appendChild( script );
})
}
const useScripts = () => {
const [isLoaded, setLoaded] = useState(false);
useEffect(() => {
Promise
.all(scripts.map(script => loadScript(script)))
.then(() => setLoaded(true));
}, []);
return isLoaded;
}
const App = () => {
const isLoaded = useScripts();
useEffect(
() => {
if(!isLoaded){
return;
}
const sliderComponent = jQuery(".img-slider");
sliderComponent.slick();
},
[
isLoaded
]
);
return (
<div className="img-slider" style={{ width: 300 }}>
<img src="https://picsum.photos/200" />
<img src="https://picsum.photos/200" />
<img src="https://picsum.photos/200" />
</div>
);
};
ReactDOM.render(<App />, document.getElementById("container"));