Search code examples
javascriptjqueryreactjsgatsbyslick.js

Gatsby jquery slick $ is not defined


I have a problem with gatsby 5, it imports jquery and slick.js to it using "Helmet" without refreshing the page, the script works but as soon as I click f5 (clear the cache), I suddenly get an error that "$ is not defined" or that "jquery s not defined"I feel that it may be a fault that they will not load in the correct js order, but I might be wrong. Will you help?

export function Head() {
  return (
    <>
      <title>Simtopia</title>
      <Helmet>
      <script
      src="https://code.jquery.com/jquery-3.6.0.min.js"
      integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
      crossorigin="anonymous"
    ></script>
         <script
      src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js"
      integrity="sha512-XtmMtDEcNz2j7ekrtHvOVR4iwwaD6o/FUJe6+Zq+HgcCsk3kj4uSQQR8weQ2QVj1o0Pk6PwYLohm206ZzNfubg=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    ></script>
           <script
      src="/js/localJS.js"
    ></script>
 </Helmet>
    </>
  )
}

Solution

  • If you are loading scripts that are mutually dependent I'd recommend using the Script API that Gatsby provides, which exposes an onLoad callback:

    import React, { useState } from "react";
    import { Script } from "gatsby";
    
    export function Head() {
      const [loaded, setLoaded] = useState(false);
    
      return (
        <>
          <Script
            src="https://code.jquery.com/jquery-3.6.0.min.js"
            onLoad={() => setLoaded(true)}
          />
          {loaded && (
            <Script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js" />
          )}
          {loaded && (
            <Script src="/js/localJS.js" />
          )}
        </>
      );
    }
    

    Note: tweak the order or the conditions accordingly


    ⚠️

    Outside the scope of the question: don't import jQuery inside React apps, or you will break the hydration. Really, don't do it.

    React (so Gatsby) creates and manipulates a virtual DOM (vDOM) while jQuery manipulates directly the real DOM. Using both will cause unwanted (re)hydration issues because when something changes in the DOM React won't be aware and vice-versa. This translates into multiple issues, but one of the most typical is finding unstyled parts of the page, non-rendered hooks when moving forward/backward using browser's arrows/history, etc.

    From React docs:

    React is unaware of changes made to the DOM outside of React. It determines updates based on its own internal representation, and if the same DOM nodes are manipulated by another library, React gets confused and has no way to recover.

    Alternatively, use React-based approaches such Reack Slick or using useRef hook when pointing DOM elements