Search code examples
javascriptreactjsreact-hooksgatsbyghost-blog

html.js loading the script only once on page load Gatsby


I am using html.js to load custom script. I have created a js file in static folder custom.js but when I am running my project it loads the script only once on first time page load but when I am navigation to other page it not loading the script.

My custom.js file

$(document).ready(function () {
    console.log("in ready");
});

My html.js file

import React from "react";
import PropTypes from "prop-types";
import { withPrefix } from "gatsby";

export default function HTML(props) {
    return (
        <html {...props.htmlAttributes}>
            <head>
                <meta charSet="utf-8" />
                <meta httpEquiv="x-ua-compatible" content="ie=edge" />
                <meta
                    name="viewport"
                    content="width=device-width, initial-scale=1, shrink-to-fit=no"
                />
                <script
                    type="text/javascript"
                    src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"
                ></script>
                <link
                    href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css"
                    rel="stylesheet"
                    type="text/css"
                />
                {props.headComponents}
            </head>
            <body {...props.bodyAttributes}>
                {props.preBodyComponents}
                <div
                    key={`body`}
                    id="___gatsby"
                    dangerouslySetInnerHTML={{ __html: props.body }}
                />
                {props.postBodyComponents}
                <link
                    rel="stylesheet"
                    href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
                />
                <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
                <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
                <script
                    type="text/javascript"
                    src={withPrefix("js/custom.js")}
                ></script>
            </body>
        </html>
    );
}

HTML.propTypes = {
    htmlAttributes: PropTypes.object,
    headComponents: PropTypes.array,
    bodyAttributes: PropTypes.object,
    preBodyComponents: PropTypes.array,
    body: PropTypes.string,
    postBodyComponents: PropTypes.array,
};

What I am doing here wrong ? Why it's loading script only once ? What I have to do load custom.js script on every page navigation?

I have also tried to include custom.js inside my Layout file in <Helmet></Helmet> but same issue.

Thanks


Solution

  • What I am doing here wrong ? Why it's loading script only once ? What I have to do load custom.js script on every page navigation?

    I think that there is a misunderstanding and a mix of context on how React and old-fashioned scripting like jQuery works. In the end, Gatsby is a React-based application.

    Among saying that Reacts manipulates a virtual DOM (vDOM) and jQuery points directly to the DOM, which has an extremely high-cost impact on performance. If you mix both approaches outside the scope of React, you can block React's hydration, potentially breaking your application.

    You can simply create a useEffect hook with empty dependencies ([]), which will be triggered once the DOM tree is loaded for each page it's included. React's lifecycle should work for your use-case without overkilling the customization of the HTML generated by Gatsby.

    Your custom.js file must have something exported. As simply as:

    const customJS =()=> console.log("I'm ready");
    
    export default customJS;  
    

    Then, on any page:

    import React, {useEffect} from "react";
    import customJS from "../path/to/custom.js";
    
    const AnyPage =(props)=>{
    
       useEffect(()=>{
         customJS()
       }, [])
    
    
    return <div>Some content for AnyPage()<div>
    }
    export default AnyPage;
    

    customJS() will be triggered only one time per page, once the DOM is loaded.

    Please, don't use jQuery along with React, it's not needed.