0

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 "./Parent";
import React, { useState } from 'react';

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

    return (
        <div>child</div>
    )
}

Parent.tsx:

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

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

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

page.tsx:

import Child from "./Child";
import Parent from "./Parent";

export default function Page() {

  return (
    <>
      <Parent>
        <Child />
      </Parent>
    </>
  )
}

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?

yuriy636
  • 11,171
  • 5
  • 37
  • 42
alEN
  • 77
  • 1
  • 6
  • 2
    If your component uses any sort of state, it has to have "use client". I think you might be assuming that if the parent has "use client" then all children automatically are "use client" but that's not the case. You need to specify it for each file. In this case, add the "use client" line whenever you're using "useEffect" and "useState" in a file as a start – wongz May 07 '23 at 18:19
  • When they say **including child components** they are talking about components called inside that component, not the one wrapped by it, being consumed with `children`. This is why a `children` of a Client Component can be a Server Component. – Youssouf Oumar May 07 '23 at 19:21

2 Answers2

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.

alexortizl
  • 2,125
  • 1
  • 12
  • 27
1

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

"use client"

import { React , useState } from 'react';

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

Aymendps
  • 1,346
  • 4
  • 20
Pouya
  • 11
  • 2