为什么我不能在Next.js 13的子组件中使用`useState`?

huangapple go评论60阅读模式
英文:

Why I cannot use `useState` in a child component in Next.js 13?

问题

The issue you're encountering is related to the usage of the "use client" directive in Next.js. According to the error message you provided, it seems that the "Child" component is importing and using the "useState" hook, which is intended for client-side components. However, none of its parent components, including "Parent," are marked with the "use client" directive, which causes them to be treated as server-side components by default.

To resolve this issue, you need to add the "use client" directive to the parent components that use client-side features like "useState." In your case, you should add "use client" to the "Parent.tsx" file because it uses the "useState" hook.

Here's the updated "Parent.tsx" file:

'use client';
import React, { useState } from 'react';

export default function Parent({ children }: {
    children: React.ReactNode
}) {
    const [s, ss] = useState(null);

    return (
        <div>{children}</div>
    )
}

By adding "use client" to the "Parent.tsx" file, it should resolve the error and allow the "Child" component to use client-side features like "useState" without any issues.

英文:

a new update in NextJS came out (with app router). I am really confused by the client/server side component relationships. I am currently experimenting with it, and it says in the docs that:

> "use client" sits between server-only and client code. It's placed at
> the top of a file, above imports, to define the cut-off point where it
> crosses the boundary from the server-only to the client part. Once
> "use client" is defined in a file, all other modules imported into it,
> including child components, are considered part of the client bundle.

Now, here goes my code (Child.tsx):

import Parent from &quot;./Parent&quot;;
import React, { useState } from &#39;react&#39;;

export default function Child() {
    const [s, ss] = useState(null);

    return (
        &lt;div&gt;child&lt;/div&gt;
    )
}

Parent.tsx:

&#39;use client&#39;;
import React, { useState } from &#39;react&#39;

export default function Parent({children} : {
    children: React.ReactNode
}) {
    const [s, ss] = useState(null);

    return (
        &lt;div&gt;{children}&lt;/div&gt;
    )
}

page.tsx:

import Child from &quot;./Child&quot;;
import Parent from &quot;./Parent&quot;;

export default function Page() {

  return (
    &lt;&gt;
      &lt;Parent&gt;
        &lt;Child /&gt;
      &lt;/Parent&gt;
    &lt;/&gt;
  )
}

Since my Parent component has 'use client' directive, according to the docs, all child compoonents must also be marked as client-side components:

> ./app\Child.tsx
>
> ReactServerComponentsError:
>
> You're importing a
> component that needs useState. It only works in a Client Component but
> none of its parents are marked with "use client", so they're Server
> Components by default.

What is the cause of this problem?

答案1

得分: 1

I think in this case the Next.js docs were somewhat misleading. What is happening in your case is that both <Parent /> and <Child /> are defined in page.tsx which is a server component by default, in that case <Parent /> is rendered as a client because it has the 'use client' directive but Child is rendered as a server component because it is declared in a server component (page.tsx) and doesn't have the 'use client' directive. To all effects <Child /> is a server component and therefore it cannot use useState. Another way of looking at this is that what <Parent /> gets in its children property is the <Child /> component already rendered (html and css) as a server component in page.tsx instead of a <Child /> component declaration to be rendered along with <Parent />. Actually passing a server component as a child to a client component in another server component is the only way in which you can have a server component inside a client component. I get this can be hard to get your head around, I recommend looking at https://nextjs.org/docs/getting-started/react-essentials#importing-server-into-client-components they have some pretty good examples there.

英文:

I think in this case the Next.js docs were somewhat misleading. What is happening in your case is that both &lt;Parent /&gt; and &lt;Child /&gt; are defined in page.tsx which is a server component by default, in that case &lt;Parent /&gt; is rendered as a client because it has the &#39;use client&#39; directive but Child is rendered as a server component because it is declared in a server component (page.tsx) and doesn't have the &#39;use client&#39; directive. To all effects &lt;Child /&gt; is a server component and therefore it cannot use useState. Another way of looking at this is that what &lt;Parent /&gt; gets in its children property is the &lt;Child /&gt; component already rendered (html and css) as a server component in page.tsx instead of a &lt;Child /&gt; component declaration to be rendered along with &lt;Parent /&gt;. Actually passing a server component as a child to a client component in another server component is the only way in which you can have a server component inside a client component. I get this can be hard to get your head around, I recommend looking at https://nextjs.org/docs/getting-started/react-essentials#importing-server-into-client-components they have some pretty good examples there.

答案2

得分: 1

需要在你的代码顶部添加&quot;use client&quot;,然后从react导入useStateReact

&quot;use client&quot;
import { React, useState } from &#39;react&#39;;

在使用状态的所有页面都需要这样做,否则它将无法正常工作。

英文:

you need to add &quot;use client&quot; at the top of your code then import both useState and React from react:

&quot;use client&quot;

import { React , useState } from &#39;react&#39;;

It is required for all pages that you are using states, otherwise it won't work.

huangapple
  • 本文由 发表于 2023年5月8日 01:50:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76195439.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定