Dynamic Imports - NextJS

Avi Kaminetzky picture Avi Kaminetzky · Jan 1, 2019 · Viewed 8.1k times · Source

I have a simple function which loads a script:

const creditCardScript = (
  onReadyCB,
  onErrorCB,
) => {
  let script = document.createElement("script");
  script.type = "text/javascript";
  script.src = process.CREDIT_CARD_SCRIPT;
  document.head.appendChild(script);

  script.onload = function() {
    ...
  };
};

export default creditCardScript;

Before I migrated to NextJS, I was importing the script with: import creditCardScript from "./creditCardScript".

Sine NextJS renders components server side in Node, care needs to be taken to ensure that any code with a reference to window (which is browser specific), doesn't get called until componentDidMount.

NextJS solves this issue by providing dynamic imports (a wrapper around react-loadable) which:

  • only load the component when needed,
  • provides an option to only load the component on client side (ssr: false).

I went ahead and implemented dynamic imports:

const creditCardScript = dynamic(import("./creditCardScript"), { ssr: false });

In componentDidMount:

componentDidMount = () => {
  creditCardScript(
    this.onReadyCB,
    this.onErrorCB
  );
};

But I'm getting this: Uncaught TypeError: Cannot call a class as a function

I've tried to convert the function to a class and use the constructor to pass in args, but my code now fails silently.

Answer

Avi Kaminetzky picture Avi Kaminetzky · Jan 1, 2019

As Neal mentioned in the comments, all I need to do is something like this in componentDidMount:

const { default: creditCardScript } = await import("./creditCardScript"); 

Link to the official tutorial