0

I understand I have an issue similar to here, Though It looks to me that this is what I am already doing.

I have a function which ads the script to the page as per below.

export const appendScript = function (scriptToAppend, sourceScript = true) {
 if (sourceScript) {
    const script = document.createElement("script");
    script.type = "text/javascript";
    script.async = false;
    script.src = scriptToAppend;
    document.body.appendChild(script);
  } else {
    const script = document.createElement("script");
    script.type = "text/javascript";
    script.async = false;
    script.innerHTML = scriptToAppend;
    document.body.appendChild(script);
  }
};

export const removeScript = (scriptToremove) => {
  let allsuspects = document.getElementsByTagName("script");
  for (let i = allsuspects.length; i >= 0; i--) {
    if (
      allsuspects[i] &&
      allsuspects[i].getAttribute("src") !== null &&
      allsuspects[i].getAttribute("src").indexOf(`${scriptToremove}`) !== -1
    ) {
      allsuspects[i].parentNode.removeChild(allsuspects[i]);
    }
  }
};

I add the scripts to the HTML as:

  componentDidMount() {
    //Jquery Plugin from the asset site. These are used always.
    appendScript("assets/js/jquery-2.2.1.min.js");
    appendScript("assets/js/jquery-migrate-1.2.1.min.js");
    appendScript("assets/bootstrap/js/bootstrap.min.js");

  }

Though one of the scripts is not loading properly when navigating through the navigation (via <Link></Link> component.

Though once I refresh the page, the script is working and I can see the script being used, e.g. pictures are showing up, owl carousel, and other visible effects.

The pagination, I never get the script to work on the next page, mainly the img are not showing up.

  {pages.map((page) => (
    <li key={page} className={page === currentPage ? "active" : "null"}>
      <Link to="#" onClick={() => onPageChange(page)}>
        {" "}
        {page}
      </Link>
    </li>
  ))}

Maybe this is as well something in the way how I am retrieving img elements in React:

<div className="image bg-transfer">
              <img src={tag.imagePath} alt="Sorry Can't Find :(" />
            </div>

Is this approach correct in order to have the scripts loaded for the react? I can't have the scripts changed much, moving from a static HTML draft to React.js. I hope there is a simple answer to this...

Raitis Lebedevs
  • 47
  • 1
  • 13
  • In which ComponentDidMount do you import it? At the root (App) level? or in the route level? – Tasos Oct 01 '20 at 10:43
  • Importing it on the component level, E.g. NavBar, which is not changing for no, but will have user information later on. And `function App() { return (
    ); }`
    – Raitis Lebedevs Oct 01 '20 at 10:49
  • You need to lift it up to the top component 'App' in order to work for every route – Tasos Oct 01 '20 at 10:59
  • Lift up the imported .js file? New to React, hence not sure if understand this term. As I understand I am not moving the State up, I only need the script to be used in several scripts, but it is not being 're-run' on links. I might not follow how the lifting up logic works though. – Raitis Lebedevs Oct 01 '20 at 11:02
  • No problem! Instead of importing the scripts in the component level inside the routes, you need to import them in the componentDidMount inside the App (top level) component – Tasos Oct 01 '20 at 11:12
  • You can also read [this guide](https://medium.com/better-programming/4-ways-of-adding-external-js-files-in-reactjs-823f85de3668). I prefer the `Helmet` method – Tasos Oct 01 '20 at 11:15
  • I was following that guide to create the above described scripts. Though I can't really put the componentDidMount as the App.js file is a function and it does not have this, should I change this to a class (tried this results even worse)? – Raitis Lebedevs Oct 01 '20 at 11:31
  • Hmm, do you remove the scripts with componentWillUnmount? – Tasos Oct 01 '20 at 11:52
  • No, I don't remove it. Should I do that? And what for? because that would lead me to think that it won't be used, but I want it to be used. – Raitis Lebedevs Oct 01 '20 at 11:53
  • No, you shouldn't in your case. How do you verify that the scripts are not loaded in other routes? – Tasos Oct 01 '20 at 11:54
  • 1) The script is supposed to do some changes to picture e.g. make circle etc, show on the owlCarousel. If I refresh the site they are being shown. 2) If I navigate from a link to link, it disappears, I believe the issue could be re-running the script somehow, though it is a .js file, not sure how to do this. 3) If I remove the script, the app shows the same issue as if it was just navigated with the links. 4) I tried as well think how to use the componentDidUpdate, but adding it to HTMl will not work, as it wouldn't be re-run. That is currently I am leaning to, possible it will work then. – Raitis Lebedevs Oct 01 '20 at 12:01
  • Have you tried reloading the scripts in the other routes? – Tasos Oct 01 '20 at 12:07
  • Yes, it is always the same. The script works fine when I refresh the page but doesn't if I render the component (four comments use it) each has the same issue. Though since I am a newbe (less than 2 month in React) Hard to understand what is the part I need and where is the actually issue. – Raitis Lebedevs Oct 01 '20 at 12:12
  • No, I mean to use a `componentDidMount` which loads the scripts in other routes – Tasos Oct 01 '20 at 12:16
  • Yes, I tried removing it from the NavBar, Putting in different routes. Then (for sake of check) put the script in both. It was showing under inspect always there, In the case when put in multiple place, it was twice or three times there. I understand actually now, that I need to somehow run it once the component does change. So that there would be a listener which 'adds' this particular script so that it would trigger the changes in the DOM elements. You helped me realise this. I don't think now I can just put it in HTML, it should be somehow triggered to be run again on certain components... – Raitis Lebedevs Oct 01 '20 at 12:22
  • Just to follow up the last one, it did still show up as the issue on the React App. – Raitis Lebedevs Oct 01 '20 at 12:23
  • In react, you shouldn't use scripts in this way. Why don't you use `npm` or `yarn` to install them in your project and import them when needed? What you are trying to do here is the equivalent of using `import jquery from 'jquery';` – Tasos Oct 01 '20 at 12:31
  • So I install the script with npm `path/toScript` ? – Raitis Lebedevs Oct 01 '20 at 12:34
  • If you want to load custom files that contain helper functions etc, you should export/import these function the easy way https://stackoverflow.com/a/38469257/5605822 – Tasos Oct 01 '20 at 12:34
  • If the script exists in the `npm` registry only. If it's a script you created see the above link – Tasos Oct 01 '20 at 12:34
  • Another way is to use this [answer](https://stackoverflow.com/a/53396827/5605822) – Tasos Oct 01 '20 at 12:37
  • Ok So I should use export in front of every single function I have added it the .js file, what should I do with the elements as `$(document).ready(function ($) {` the same, export?. Mainly the functions like `$(window).load(function () { initializeOwl(); bgTransfer(); });` are I guess my concern. I don't want to extract each one by one (unless it will be needed). – Raitis Lebedevs Oct 01 '20 at 12:40
  • I think you had a bad start with React (we all had). You can completely abort the use of jQuery and use React instead. For example, instead of `$(document).ready()` you can put the same code inside the `componentDidMount()` and it runs when the component is mounted for the first time. – Tasos Oct 01 '20 at 12:44
  • 1
    Understood how to achieve what I want, though not ideal, will work for me now. Once i will finish all, will focus on re-writing code better! See it in the solution bar :) – Raitis Lebedevs Oct 01 '20 at 13:28

1 Answers1

1

Thanks to the enthusiast @Tasos Bu, I understood what I was missing, and he lead me to the idea to add the script which I need as per below. This solved all of my problems (not all, still not a millionaire). Here is how I did it. I am adding and removing the scripts which still use JQuery to the HTML after it is rendered.

  componentDidMount() {
    //All custom Js functions, responsivness etc.
    appendScript("assets/js/custom.js");
  }
  componentDidUpdate() {
    //All custom Js functions, responsivness etc.
    removeScript("assets/js/custom.js");
    appendScript("assets/js/custom.js");
  }
Raitis Lebedevs
  • 47
  • 1
  • 13