How can I use the external javascript variables in a nextjs page?

614 views Asked by At

Now I'm building a webpage that shows a ranking of items. I'm fetching datas with an external javascript file and using it by putting tag in nextjs page. The script uses the window variable, so I couldn't make it API and execuse it on the serverside.

Now my page is like below.

<div>
<Script src="/weeklyRanking.js" />
</div>

In the js, I have items variable which is an array, and I want to use it in a page like below.

{items.map((item)=>(
 <div>{item}<div>
))}

How can I pass the variable from script tag to page?

I tried below, weeklyRanking.js

let items = [item1,item2,item3];
window.items = items;

page.jsx

import Script from 'next/script'

const page = () => {
  const [items, setItems] = useState([]);
  }
  useEffect(() => {
    setItems(window.items)
  }, [])
  
  return (
    <>
    {items.map((item)=>(
    <div key={item}>{item}</div>
    ))}
    <Script src="/weeklyRanking.js" />
    </>
  )
}

export default page

The result is the items variable is undefined.

3

There are 3 answers

1
Top Dev On

The useEffect hook runs before the weeklyRanking.js script has finished loading, resulting in window.items being undefined.

You can try with this(worked for me).

import Script from 'next/script'

const page = () => {

  const [items, setItems] = useState([]);

  useEffect(() => {
    const handleScriptLoad = () => {
      setItems(window.items);
    };

    console.log(items); // ['aaa', 'bbb', 'ccc']

    const scriptElement = document.createElement('script');
    scriptElement.src = '/weeklyRanking.js';
    scriptElement.async = true;
    scriptElement.onload = handleScriptLoad;

    document.body.appendChild(scriptElement);

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

  return (
    <>
    {items.map((item)=>(
    <div key={item}>{item}</div>
    ))}
    </>
 )
}

export default page

weeklyRanking.js

let items = ['aaa', 'bbb', 'ccc'];
window.items = items;
2
Atlas On

To pass the items variable from the external JavaScript file to your Next.js page, you can modify the script in weeklyRanking.js to set the items variable as a global variable. Here's how you can do it:

In weeklyRanking.js: javascript // Define the items variable as a global variable window.items = [item1, item2, item3];

// Rest of your code

In your Next.js page: jsx

import Script from 'next/script';
import { useEffect, useState } from 'react';

function YourPage() {
  const [items, setItems] = useState([]);

  useEffect(() => {
    // Access the global items variable after the script has loaded
    setItems(window.items);
  }, []);

  return (
    <div>
      {items.map((item) => (
        <div key={item}>{item}</div>
      ))}
      <Script src="/weeklyRanking.js" />
    </div>
  );
}

export default YourPage;
0
argbo On

I would start by examining why you need to load this data in a separate script. Polluting the global namespace can be dangerous.

If you do go down this path, ensure that your script is actually loading and running. You can use a debug statement to make sure it executes before your page hydrates.

Using src="/weeklyRanking.js" is telling Next to look for the script at /. Try importing your script like this to ensure you are serving the absolute path to the script on the server:

import weeklyRanking from "./weeklyRanking.js"

...

<Script src={weeklyRanking} />