Closed b-novikov-ipersonality closed 2 years ago
Open about.tsx file in pages folder to see typescript error.
You are exporting the <NewHero/>
component as default, so you don't need the .then
block when you are importing it.
const Component = dynamic(() => import("../components/Component").then(module => module.Component); // wrong
const Component = dynamic(() => import("../components/Component") // correct
Only use the .then module, when you are using named export from the file you are importing from.
// NewHero.tsx
function NewHero(){return ....}
export NewHero
.
.
// About.tsx
const Component = dynamic(() => import("../components/Component").then(module => module.NewHero);
for further reading: NextJs Dynamic Import
Open index.tsx file and corresponding page in browser, open Console you will see a warning: Did not expect server HTML to contain a
<section> in <div>
.Open furthermore.tsx file and corresponding page in browser, in Console you will see warning Text content did not match. Server: "Hero header" Client: "New Hero header"
These two warnings will be gone when you export the <Hero/>
component in a normal way.
export default Hero
I didn't find a solid reference for the usage of the export default dynamic()
method, but personally, I am using it only with nextjs pages whenever I need this page to not render in the server-side
export default dynamic(() => Promise.resolve(CartPage), { ssr: false });
This could be helpful if you are using the browser local storage to store the cart times, or when you are doing client-side authentication and need to prevent the app to render the UserProfile page, and so on..
But when talking about code splitting and lazy loading a component with nextjs, I always use dynamic import
By the way, NextJs present a new API to handle client and server component based on React18
but it is still on beta, you can read more from here
@atarek12 please read the issue carefully and check codesandbox I provided. NewHero
component is a named export.
@b-novikov-ipersonality, you are misunderstanding the difference between named
and default
exports.
// NewHero.tsx
const NewHero = () => {
return (
<section>
<h1>New Hero header</h1>
<p>lorem lorem lorem</p>
</section>
);
};
export default NewHero; // this is a default export
// we can import this with any name
import NewHero from 'path-to-NewHero' // correct
import SuperHero from 'path-to-NewHero' // correct
const NewHero = dynamic(() => import("path-to-NewHero") // correct
const NewHero = dynamic(() => import("path-to-NewHero").then((mod) => mod.default) // correct
const NewHero = dynamic(() => import("path-to-NewHero").then((mod) => mod.NewHero) // wrong
);
export const NewHero = () => { // named export
return (
<section>
<h1>New Hero header</h1>
<p>lorem lorem lorem</p>
</section>
);
};
// we must import this with its predefined name
import {NewHero} from 'path-to-NewHero' // correct
import {NewHero as SuperHero} from 'path-to-NewHero' // correct
const NewHero = dynamic(() => import("path-to-NewHero") // wrong
const NewHero = dynamic(() => import("path-to-NewHero").then((mod) => mod.default) // wrong
const NewHero = dynamic(() => import("path-to-NewHero").then((mod) => mod.NewHero) // correct
For further reading: MDN
@atarek12 Mr. Senior Engineer, could you please carefully read my issue and carefully inspect code I provided? You should try to reproduce problem first before leaving misleading comments.
edit: to make things clear, I removed default export from NewHero
component, leaving only named export
I don't why you are talking to me like this, I just needed to help, by the way, I did not see type errors now after your updates.
@atarek12
@b-novikov-ipersonality it is not visible on my side
@atarek12 you need to be logged in to see the error. It might be a better idea to reproduce it locally.
@b-novikov-ipersonality now I can see it, I have figured out that you need to pass the component props interface manually into the dynamic component. The typescript should detect it by itself, but it has trouble when using Promise.then()
const NewHero = dynamic<NewHeroProps>(() =>
import("../components/NewHero").then((mod) => mod.NewHero)
);
Makes sense. Thank you for looking into it, @atarek12 Closing the issue because other mentioned problems are related to undocumented feature.
@b-novikov-ipersonality I kindly ask you to refrain from comments like "Mr. Senior Engineer," in the future, as it might sound disrespectful towards @atarek12 who tried to help you. Please have a look at our Code of Conduct.
I'm happy to see that the problem sorted itself.
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.
Run
next info
(available from version 12.0.8 and up)What version of Next.js are you using?
12.0.8
What version of Node.js are you using?
16.13.2
What browser are you using?
Google Chrome Version 99.0.4844.11 (Official Build) dev (64-bit)
What operating system are you using?
Linux (Arch)
How are you deploying your application?
next start | digital ocean
Describe the Bug
1) Typescript error when dynamically import named component (see To Reproduce section for codesandbox and instructions) 2) When exporting component as a dynamic module
you get
Did not expect server HTML to contain a <section> in <div>
warning in console if and only ifssr
property is set totrue
. 3) When dynamically imported component is used with dynamically exported component in the same component, another warning occurs:Text content did not match. Server: "Hero header" Client: "New Hero header"
Expected Behavior
1) When dynamically importing named component, type checking does not result in error 2) Component dynamically exported with
ssr
set totrue
does not give a warning 3) Don't know if its legal to use dynamic import with dynamically exported component in one place. If it is, it should give a warning.To Reproduce
https://codesandbox.io/s/beautiful-proskuriakova-s1lii?file=/pages/index.tsx
1) Open
about.tsx
file inpages
folder to see typescript error. 2) Openindex.tsx
file and corresponding page in browser, open Console you will see a warning:Did not expect server HTML to contain a <section> in <div>.
3) Openfurthermore.tsx
file and corresponding page in browser, in Console you will see warningText content did not match. Server: "Hero header" Client: "New Hero header"
Steps to reproduce problem №1: 1) Create a component that uses named export:
2) Using
dynamic
, import that component:3) You will see Typescript doesn't like
Component
.Steps to reproduce problem №2: 1) Create a component:
2) Export it using
dynamic
:3) Use the
Component
somewhere:4) Open
AnotherComponent
in a browser, open the console, see the error.Steps to reproduce problem №3: 1) Use component from problem №1 somewhere in
AnotherComponent
from problem №2 - basically you need to have component imported dynamicallydynamic(() => import(...))
and component exported dynamically for error to occur 2) See warning in console