Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v13.0.2 broke something to do with dynamic imports #43483

Closed
1 task done
zlwaterfield opened this issue Nov 28, 2022 · 13 comments
Closed
1 task done

v13.0.2 broke something to do with dynamic imports #43483

zlwaterfield opened this issue Nov 28, 2022 · 13 comments
Labels
bug Issue was opened via the bug report template.

Comments

@zlwaterfield
Copy link
Contributor

zlwaterfield commented Nov 28, 2022

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

 Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.1.0: Tue Sep 20 10:43:35 PDT 2022; root:xnu-8792.40.108.191.2~2/RELEASE_ARM64_T6000
    Binaries:
      Node: 16.17.1
      npm: 8.15.0
      Yarn: 1.22.19
      pnpm: 7.17.0
    Relevant packages:
      next: 13.0.1
      eslint-config-next: 13.0.0
      react: 18.2.0
      react-dom: 18.2.0

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

v13.0.2 broke dynamic imports. I'm importing the quill editor (https://github.com/zenoamaro/react-quill) and it's throwing a "document is not defined" error. I've verified it works on previous versions before v13.0.2, but no versions starting at v13.0.2.

Note: this only happens after a build (next build && next start), it is not occurring with next dev

Here is what my quill component looks like:

import dynamic from "next/dynamic";

import { FC } from "react";

const QuillNoSSRWrapper = dynamic(import("react-quill"), {
  ssr: false,
  loading: () => <p>Loading ...</p>,
});

const modules = {
  toolbar: [
    [{ header: "1" }, { header: "2" }],
  ],
  clipboard: {
    // toggle to add extra line breaks when pasting HTML:
    matchVisual: false,
  },
};

const formats = ["header", "size", "bold", "italic", "underline", "blockquote", "list", "bullet", "indent"];

export const RichTextEditor = ({ value, onChange }) => {
  return (
    // @ts-ignore-next-line
    <QuillNoSSRWrapper
      modules={modules}
      formats={formats}
      value={value}
      onChange={(e) => {
        onChange(e);
      }}
      placeholder="Write stuff"
    />
  );
};

and here is the error:
Screenshot 2022-11-28 at 6 04 03 PM

Expected Behavior

It should render without an error in v13.0.2+.

Link to reproduction - Issues with a link to complete (but minimal) reproduction code will be addressed faster

N/A

To Reproduce

Take my quill component example above and render the component in your code, run next build && next start and try to view the page it is rendering on.

It will work on v13.0.1 and not on v13.0.2.

@zlwaterfield zlwaterfield added the bug Issue was opened via the bug report template. label Nov 28, 2022
@Fredkiss3
Copy link
Contributor

Firstly Please create a reproduction example, as it helps people who want to help try and test and maybe come up with a solution faster.

You could easily create one with stackblitz, here is a simple link to setup for reproduction : https://stackblitz.com/fork/github/vercel/next.js/tree/canary/examples/reproduction-template

Secondly, I’ve had some problems with dynamic imports and I think it is because they can’t be used in server components, to import them you could try putting the "use client" directive on the component that import them. 🤔

@Fredkiss3
Copy link
Contributor

There is also a problem with the code you gave, next/dynamic takes a callback but you wrote an import directly, it should be :

const QuillNoSSRWrapper = dynamic(() => import("react-quill"), {
  ssr: false,
  loading: () => <p>Loading ...</p>,
});

@zlwaterfield
Copy link
Contributor Author

Ah thank you @Fredkiss3, that seems to be it.

@njarraud
Copy link

njarraud commented Dec 6, 2022

Secondly, I’ve had some problems with dynamic imports and I think it is because they can’t be used in server components, to import them you could try putting the "use client" directive on the component that import them. 🤔

I tried that but it doesn't work. Looks like this dynamic import is always pre-rendered despite {ssr: false}.

@Fredkiss3
Copy link
Contributor

@njarraud I think that’s intended, server components are only executed once on the server, they can’t support dynamic import since dynamic import needs to happen on the client (most of the time).

@njarraud
Copy link

njarraud commented Dec 6, 2022

I used the dynamic import of a 'use client' component inside another 'use client' component.
There has to be a solution to execute code on the client only?

@Fredkiss3
Copy link
Contributor

I dont understand you well, could you give an example of what you are trying to do ?

@njarraud
Copy link

njarraud commented Dec 6, 2022

I want to execute some code on the client only (as it uses document). However at the moment, Next also tries to pre-render it on the server as well which results in ReferenceError: document is not defined error on the server.

'use client';

const ChildComponent = dynamic(() => import('./ChildComponent'), { ssr: false });

const ParentComponent = () => {
    return <ChildComponent />
}
'use client';

// Import libraries using browser only API to use in ChildComponent

const ChildComponent = () => {
    console.log('Shall not be logged in the server console but it is')

    return <div>{whatever here}</div>
}

@Fredkiss3
Copy link
Contributor

You're totally right, there is a bug with dynamic components, when is tested your within pages directory it works as intented, but within app directory it doesn't.

The wrokaround i found is to not show the dynamic component on the first render, so that it won't run on the server, then run a useEffect on the client to show after, like this :

'use client';
import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';

const ChildComponent = dynamic(() => import('./ChildComponent'), {
  ssr: false,
});

export default function ParentComponent() {
  const [isChildShown, setShowChild] = useState(false);

  useEffect(() => {
    setShowChild(true);
  }, []);

  return <>{isChildShown && <ChildComponent />}</>;
}

I also managed to do a little reproduction template here : https://stackblitz.com/edit/nextjs-zkhpkm?file=app%2Fpage.js,pages%2Fproblem.js

@Fredkiss3
Copy link
Contributor

Openned an issue here : #43764

@Fredkiss3
Copy link
Contributor

@njarraud This issue has been fixed in the latest canary release (you can install it with next@canary and should be fixed by the time next@13.0.7 come out).

@njarraud
Copy link

njarraud commented Dec 8, 2022

Thanks, it works.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 7, 2023

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 7, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests

3 participants