Problems invoking external Libs functions in React

Asked

Viewed 49 times

2

I’m developing a website in React and I need to use an external Javascript lib (I don’t have his npm package), so I have a link to import on the site. At first I thought of importing it into HTML even with the tag script, but I could not access any of the functions, giving only the error 'funcao' is not defined .

After that I went after a way to import only where I will need and I came across the code below that actually created the tag script, but once again I did not succeed to invoke the function.

const loadScript = async () => {
    const script = document.createElement("script");
    script.type = "text/javascript";
    script.id = "ID do script";
    script.src = `URL DA LIB`;
    script.async = false;
    document.body.appendChild(script);
    setLoaded(true)
    return () => {
      document.body.removeChild(script);
    };
}

I’m calling this function up using the useEffect and even put a state to only invoke the function after the loaded for true, but similarly, I keep getting an error when compiling because the function does not exist.

I can use the functions by the browser console, which I understand indicates that the import is working correctly, so my question is how should I call this function? I’ve tried to funcao(), window.funcao() and window['funcao'] and nothing, always having the same mistake of 'funcao' is not defined .

  • Is the library an ES6 module or is it a normal script? If it is an ES6 module, why are you including the script with the type text/javascript? If it is a normal script, why are you trying to import? Anyway, include the tag script within a react hook, although it is not prohibited or impossible, it is, most of the time, bad sign.

  • I believe it is normal script. I am importing by following the instructions of the Pagseguro API for creating transparent checkout. I even found a package that does this checkout, but I will need this checkout for recurring payment and for standard cart, which this package does not support. For reference, follow the link of the documentation of the secure page: https://dev.pagseguro.uol.com.br/reference/checkout-transparent#transparent-library-javascript

  • I tried to reproduce your problem and answered your question. The only detail I did not consider and I suppose you did not pass one async function to the useEffect - I assumed that, because in those cases the React complains and shows an error message on the console. As you did not mention this message, anyway, if the answer does not solve your problem, add more details.

1 answer

5


To try to play your error, I created the following files:

index.html

<html lang="en">
<head>
    <meta charset="UTF-8">    
    <title>Document</title>
    <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
</head>
<body>
    <div class="root"></div>
    <script type='module' src='app.js'></script>
</body>
</html>

app js. consistent in a Java module containing a simple React application (I didn’t use JSX or create-React-app because it didn’t seem relevant to the problem):

 const h = React.createElement;

 function Teste(){

     const [sum, setSum] = React.useState("...");            
     React.useEffect(()=>{
         const script = document.createElement('script');
         script.type = "text/javascript";
         script.src = "script.js";
         script.async = false;
         document.body.appendChild(script);
        
         script.addEventListener('load', ()=>{
            setSum(soma(1, 2));
         });

         return () => {
            document.body.removeChild(script);
          };
         
     }, []);

     return h('h1', [], `${sum}`);              
 }

 const root = document.querySelector('.root');
 ReactDOM.render(h(Teste), root);            

and script js., consistent in a normal Avascript file for testing:

function soma(a, b){
  return a + b;
}

The result was as follows: the only error I identified that prevents you from accessing the functions of the script you want to load consists of invoking the function setLoaded(true), right after attaching the element to the document.body. Of course, at this time, the script has not yet been loaded and its functions and variables are not yet available.

This error can be corrected by adding a eventListener, something like:

script.addEventListener('load', ()=>{
            setLoaded(true);
         });

In addition, the functions of the loaded script were perfectly accessible.

That said, it may be important to point out that I’m not sure that this method with useEffect be the most recommended. I would simply include in the HTML code before the scripts React. But, except for the recommendation of the team responsible for React, and I know no recommendation in this regard, I must admit that this is perhaps only a preference of mine.

And finally, if the solution doesn’t solve your problem, add more details to your question so that your problem can be replicated by people trying to answer.

  • It is important to remove the Cleanup of useEffect

  • @Rafaeltavares, in fact, when an element is removed from the program (that is, when there is no more reference to it), the Garbage Collector removes the events associated with that element (unless the creation and removal is in a loop and the GC does not work in a separate thread). However, your comment realizing me that I forgot to remove the script itself in the useEffect, if not the page will end with multiple copies of that script associated with the document.body. I’ll correct that for you.

  • 1

    You’re right, I mistook the code, I didn’t pay attention. The event is associated with the element you removed, so you don’t necessarily need to remove the System.

  • 1

    In your example, you have associated Event Listener focus to the object window. Since window is never removed in Javascript, it is to be expected that every time the component is mounted, it will add more window. In my example, Event Listener is associated with the element script which is removed every time the component is disassembled and with it the Event Listener load.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.