skip to Main Content

I am inserting an external js script to a react website where it is only allowed to insert js at a single place that applies to all the pages and HTML can be added to a specific page. The external script is intended to run for a specific page. When that page is loaded directly the script works but when I open that page using the navbar button it does not load the script although I added a click event to load the specific function.

I added the html element directly to that specific page body, it takes some time to load and this element is referred in the external script.

The element with the id widget that I added to the specific page as custom html ( custom HTML can be inserted into a specific page) loads after some time. When I used set timeout inside showWidgetDelayed it worked on clicked but not without or when I double click the button.

Is there any way to wait for the DOM to load on SPA website? As window.onload and such onload functions work once when the website is loaded and not when you switch pages in already loaded websites.

    const scriptUrl = "https:portal.v7.js";
    const script = document.createElement("script");
    script.src = scriptUrl;
    const loadDevPortalScript = () => {
        script.onload = () => {
        portal.show(
         container: "widget",  // this element with id widget is already added to specifc page html
         ....
        )
}
 const showWidgetDelayed = () => {
        portal.show(
         container: "widget",
         ....
        )
}
   const portalButton = document.querySelector(
        "div.Header-topuTMpygDG4e1V.rm-Header-top > div > div:nth-child(2) > a:nth-child(3)"
    );

    portalButton.addEventListener("click", showWidgetDelayed);

2

Answers


  1. Chosen as BEST ANSWER
    function waitForElm(selector) {
        return new Promise(resolve => {
            if (document.querySelector(selector)) {
                return resolve(document.querySelector(selector));
            }
    
            const observer = new MutationObserver(mutations => {
                if (document.querySelector(selector)) {
                    resolve(document.querySelector(selector));
                    observer.disconnect();
                }
            });
    
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        });
    }
        waitForElm('#widget').then((elm) => {
         portal.show()
    

    }

    I used this mutation observer and it worked :))


  2. Since you’re working with a React application, it’s possible that the DOM is not fully rendered when your script is trying to access the element with the "widget" id. Instead of using a click event, you can use React’s lifecycle methods or hooks to ensure the script runs when the component is mounted.

    If you’re using class components, you can use the componentDidMount lifecycle method. If you’re using functional components, you can use the useEffect hook. Here’s how you can implement the external script loading and execution using the useEffect hook in a functional component:

    1. Create a new functional component for your specific page where you want to run the script:
    import React, { useEffect } from 'react';
    
    const SpecificPage = () => {
      useEffect(() => {
        const loadDevPortalScript = () => {
          const scriptUrl = 'https://portal.v7.js';
          const script = document.createElement('script');
          script.src = scriptUrl;
    
          script.onload = () => {
            portal.show({
              container: 'widget',
              // ...
            });
          };
    
          document.body.appendChild(script);
          return () => {
            document.body.removeChild(script);
          };
        };
    
        loadDevPortalScript();
      }, []);
    
      return (
        <div>
          {/* Your page content goes here */}
          <div id="widget"></div>
        </div>
      );
    };
    
    export default SpecificPage;
    
    1. Use the SpecificPage component in your application and ensure it’s rendered when you navigate to the specific page.

    This approach will ensure the script is loaded and executed when the SpecificPage component is mounted, and the DOM element with the "widget" id should be available when the portal.show function is called.

    The useEffect hook with an empty dependency array [] will only run once, when the component is mounted. The return statement inside useEffect will run a cleanup function when the component is unmounted, removing the script from the DOM.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search