YaddyVirus
YaddyVirus

Reputation: 301

Next.js inline script only loads once

I've implemented Tiny Slider in my Next.js app which requires an inline script on the page to control the slider's behavior. Now while the script loads properly the first time I launch index.js, however whenever I navigate to another page using Link and come back to index.js, the script doesn't load.

Here's how I've written the script in index.js

 {/* Script */}
        <Script id='tester'>
          {`
            var slider = tns({
              container: '.my-slider',
              items: 6,
              autoplay: true,
              autoplayTimeout: 2000,
              gutter: 20,
              autoplayButtonOutput: false,
              controls: false,
              navPosition: 'bottom',
              nav: false,
              mouseDrag: true,
              arrowKeys: true,
              responsive: {
                300: {
                  items: 2,
                  gutter: 50,
                  center: true,
                  fixedWidth: 250,
                },
                700: {
                  items: 3,
                  gutter: 50,
                  center: true,
                  fixedWidth: 250,
                },
                1440: {
                  items: 3,
                  gutter: 50,
                  fixedWidth: 250,
                  center: true,
                }
              }
            });
          `}
        </Script>

I need the script to load every time index.js loads, not just the first time around. Any ideas on how I can do this? The entire code is here - https://github.com/YaddyVirus/Esttheva

Upvotes: 6

Views: 1918

Answers (1)

Logan Anderson
Logan Anderson

Reputation: 581

Here are the steps to adding tiny-slider to a next.js app.

  1. Add a pages/_document.js to load the styles
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tiny-slider/2.9.2/tiny-slider.css" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
  1. Here is an example page that loads the slider
import { useEffect, useRef } from "react";

const App = () => {
  const ref = useRef(true);

  useEffect(() => {
    let slider;
    // Tiny slider only can be loaded once and can only be loaded clint side
    if (typeof window !== "undefined" && ref.current) {
      ref.current = false;
      // Lazy load the slider code client side
      import("tiny-slider").then((x) => {
        slider = x.tns({
          container: ".slider",
          items: 3,
          slideBy: "page",
          autoplay: true
        });
      });
    }
    // Destory the slider when it is unmouted
    return slider?.destroy();
  }, []);

  return (
    <div>
      <div className="slider">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
      </div>
    </div>
  );
};

export default App;

Link to code sandbox: https://codesandbox.io/s/tina-slider-nextjs-0z8zi6?file=/pages/index.js:0-806

Here is a couple of key notes about the solution

  • The ref keeps track of if the hook as already been called (as of react 18 hooks get called twice in dev mode)
  • We use typeof window !== "undefined" to ensure that tiny-window only gets loaded client side and not on the server (this causes a "window is undefined" Error)
  • We are calling the tns function as per the docs

Upvotes: 4

Related Questions