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

Dot notation client component breaks consuming RSC. #51593

Open
1 task done
Thinkscape opened this issue Jun 21, 2023 · 15 comments
Open
1 task done

Dot notation client component breaks consuming RSC. #51593

Thinkscape opened this issue Jun 21, 2023 · 15 comments
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template.

Comments

@Thinkscape
Copy link

Thinkscape commented Jun 21, 2023

Verify canary release

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

Provide environment information

Operating System:
      Platform: linux
      Arch: x64
      Version: #22 SMP Tue Jan 10 18:39:00 UTC 2023
    Binaries:
      Node: 16.17.0
      npm: 8.15.0
      Yarn: 1.22.19
      pnpm: 7.1.0
    Relevant packages:
      next: 13.4.7-canary.2
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 4.9.5

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue or a replay of the bug

https://codesandbox.io/p/sandbox/winter-bash-kvw9lz?file=%2Fapp%2FComponent.tsx

To Reproduce

  • Given I have a (by default) React server component
  • I import a React client component boundary (one with "use client" clause)
  • The component module happens to use dot notation for composition of several components
  • Page crashes with Error: Unsupported Server Component type: undefined

Describe the Bug

Unhandled Runtime Error
Error: Unsupported Server Component type: undefined

Call Stack
attemptResolveElement
node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1484:8)

or

node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/loaders/next-flight-loader/module-proxy.js (51:14) 
@ Object.get
Error: Cannot access .Foo on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

Expected Behavior

Code compiles without fail.

Which browser are you using? (if relevant)

irrelevant

How are you deploying your application? (if relevant)

Vercel

@Thinkscape Thinkscape added the bug Issue was opened via the bug report template. label Jun 21, 2023
@github-actions github-actions bot added the area: app App directory (appDir: true) label Jun 21, 2023
@chillardinho
Copy link

chillardinho commented Jun 21, 2023

have you tried export const A, export const B, then import * as C and using them as C.A, C.B?

@Thinkscape
Copy link
Author

When I tried attaching the other components as props on a function (object), like so:

function Foo(){
  return <>foo</>;
}

function Component({ children }: { children: React.ReactNode }) {
  return children;
}

Component.Foo = Foo;

export { Component };

... I'm getting a new error:

node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/loaders/next-flight-loader/module-proxy.js (51:14) @ Object.get
Error: Cannot access .Foo on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

So I'm assuming it's a known limitation 🤷

@Thinkscape
Copy link
Author

have you tried export const A, export const B, then import * as C and using them as C.A, C.B?

This workaround would work on my own components, but wouldn't for 3rd party packages that use this style of composition...

@PHILLIPS71
Copy link

I'm running into a similar issue with components using dot notation, it's a really convenient convention and disappointing that it's something that doesn't seem to be supported. I know other component libraries use a similar approach in constructing components such as https://github.com/react-bootstrap/react-bootstrap.

I'm also constructing components like this across my application, but am also running into the same issue that you're encountering.

'use client'

import NavigationBrand from '@/components/navigation/NavigationBrand'
import NavigationContent from '@/components/navigation/NavigationContent'
import NavigationItem from '@/components/navigation/NavigationItem'
import NavigationLink from '@/components/navigation/NavigationLink'
import NavigationPortal from '@/components/navigation/NavigationPortal'
import NavigationSegment from '@/components/navigation/NavigationSegment'

const Navigation = React.forwardRef<HTMLElement, NavigationProps>((props, ref) => {
  // omitted for breverity
})

Navigation.displayName = 'Navigation'

export default Object.assign(Navigation, {
  Brand: NavigationBrand,
  Content: NavigationContent,
  Item: NavigationItem,
  Link: NavigationLink,
  Portal: NavigationPortal,
  Segment: NavigationSegment,
})
const NavigationMobile: React.FC<NavigationProps> = (props) => (
  <Navigation orientation="horizontal" {...props}>
    <Navigation.Brand>
      <Image src="/images/logo.png" alt="ogo" height={40} width={128} priority />
    </Navigation.Brand>
  </Navigation>
)

It then produces the same issue below when used within the app directory

Error: Cannot access .Brand on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

@kiner-tang
Copy link
Contributor

I had the same problem with antd in app router mode and hope to get it resolved soon.
image
image

@li-jia-nan
Copy link
Contributor

Have the same problem.

@emmgfx
Copy link

emmgfx commented Jul 24, 2023

I also have the same problem. I've think about updating some components removing the dot notation, but doesn't looks like a good solution.

@Jared-Dahlke
Copy link

i am having this issue as well

@marceloverdijk
Copy link

Is there any official feedback from the next.js team on this?
The new App Router mechanism seem to have some open ends...

I'm now adding 'use client' to pages where I need dotted components (e.g. from react-bootstrap), but it doesn't feel good. Neither I'm sure what the impact is doing that for a SSG...

@mryechkin
Copy link

Echoing @marceloverdijk - I've had to do the same in my projects, and it would be great to hear an official stance on this pattern.

@gaearon
Copy link
Contributor

gaearon commented Oct 5, 2023

I'm not on the Next.js team, but I'd say we don't generally consider this very idiomatic:

export default Object.assign(Navigation, {
  Brand: NavigationBrand,
  Content: NavigationContent,
  Item: NavigationItem,
  Link: NavigationLink,
  Portal: NavigationPortal,
  Segment: NavigationSegment,
})

I'd say the idiomatic way would be to express this with multiple exports. And then use import * as Navigation. But that indeed doesn't give you a pretty <Navigation> root item so I get why it's maybe a bit less pretty.

I think it would make sense for third party packages to move into that direction. That's better for tree shaking etc too. A temporary workaround would be a 'use client' file that re-exports these as named exports.

@AhmedBaset
Copy link
Contributor

Thanks for the answer Dan @gaearon
My cause is slightly different, this issue only occurs when I lazy load components with dynamic(). Is there a solution?

const WalletSummary = dynamic(() =>
  import("@/components/wallet-summary").then((mod) => mod.WalletSummary)
);

⨯ Internal error: Error: Cannot access WalletSummary.then on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

@iankduffy
Copy link

Thanks for the answer Dan @gaearon My cause is slightly different, this issue only occurs when I lazy load components with dynamic(). Is there a solution?

const WalletSummary = dynamic(() =>
  import("@/components/wallet-summary").then((mod) => mod.WalletSummary)
);

⨯ Internal error: Error: Cannot access WalletSummary.then on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

All have the same issue, before this, I had an object of components that would dynamically loaded and pick of it type.

import dynamic from "next/dynamic";

interface Props {
  [key: string]: unknown;
}

export const GenericPageComponents: Props = {
  test: () => <h1>test</h1>,
  hero: dynamic(() => import("./components").then((re) => re.Hero)),
  searchBar: dynamic(() => import("./components").then((res) => res.SearchBar)),
  contentRow: dynamic(() =>
    import("./components").then((res) => res.ContentRow)
  ),
};

I made a search bar component use client and now I get the same error:

Cannot access SearchBar.then on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

acouch added a commit to navapbc/simpler-grants-gov that referenced this issue May 23, 2024
## Summary
Fixes #6 

### Time to review: __60 mins__

## Changes proposed

### Move pages from page to app router:

1. Move all pages to
[`[locale]`](https://next-intl-docs.vercel.app/docs/getting-started/app-router/with-i18n-routing#getting-started)
folder
2. Add
[`generateMetata()`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function)
function and [next-intl
`getTranslations()`](https://next-intl-docs.vercel.app/docs/environments/metadata-route-handlers#metadata-api)
implementation
* @rylew1 commented we could remove this from each page. To do that we
could use [prop
arguments](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#with-segment-props)
and update the based on the param. There is also more we can do with the
metadata to properly add [app links and twitter
cards](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#applinks).
TODO: create ticket
4. Replace i18n's `useTranslation` with next-intl's `useTranslations`
5. Remove hard-coded strings that were present b/c we were still b/w
i18next and next-intl

#### Changes
* [Move process page to
app](32ba4ee)

* [Move research page to
app](5b5ad1a)

* [Move health page to
app](a3e6255)

* [Move feature flag page to
app](395baed)
* [Move search page to app
router](1e261e3)
* [Move newsletter pages to app
router](b509ef8)
* [Move home page to app
router](de1be98)
* [Move home page to app
router](74077ae)
* [Move 404 page to app
router](ccbc956)

### Misc

1. [Delete hello
api](5bad6ea)
     * This was left from the project creation
2. [Add USWDS icon
component](0120c7b)
* as noted in a slack discussion, when trying to access [one of the
icons](https://github.com/trussworks/react-uswds/blob/main/src/components/Icon/Icons.ts)
using `<Icon.Search/>` next errors: `You cannot dot into a client module
from a server component. You can only pass the imported name through`.
I'm not sure why it thinks the Icon component is a client module. [Dan
A.
suggests](vercel/next.js#51593 (comment))
trussworks should re-export as named exports. I tried importing the SVGs
directly from the trussworks library but [svgr requires a custom webpack
config](https://react-svgr.com/docs/next/) which is a road I didn't want
to go down and [react svg](https://www.npmjs.com/package/react-svg)
through an error in the app router 😥 .
* I implemented @sawyerh 's
[suggestion](0120c7b#diff-dadb35bd2f3f61f2c179f033cd0a2874fc343974236f2fb8613664703c751429),
which did not work initially b/c next reported the USWDS icon was
corrupt, which was fixed by adding a `viewBox` to the svg element 😮‍💨 .
* [Remove unused
WtGIContent](75490f7)

### Layout and component updates
* [Move layout and update for app
router](af112fd)

* [Update global components for the app
router](40119e6)

### Remaining next-intl config and removal of 

* [Move i18n strings for app
router](eb3c07c)

* [Adds next-intl config and removes
i18n](c546571)

* [Update tests for app
router](3b9b193)

* [Removes i18next and next-i18n
packages](9d2e08a)

* [Update storybook settings for app
router](39f115d)
@ITenthusiasm
Copy link

That's better for tree shaking etc too.

In situations where the expectation is that all of the "sub components" must be used, this point doesn't really hold up as valid. Just wanted to drop that in as a consideration.

Curious to know why the common export approach for dot notation components isn't idiomatic anymore as well. Previously, the React docs encouraged it. I get that now we're running into issues with RSCs, but that isn't sufficient justification for considering this approach to exports non-idiomatic. (Nor does it help anyone working with packages that can't/won't pivot in this way within a reasonable period of time.)

acouch added a commit to navapbc/simpler-grants-gov that referenced this issue Sep 18, 2024
Fixes #6

1. Move all pages to
[`[locale]`](https://next-intl-docs.vercel.app/docs/getting-started/app-router/with-i18n-routing#getting-started)
folder
2. Add
[`generateMetata()`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function)
function and [next-intl
`getTranslations()`](https://next-intl-docs.vercel.app/docs/environments/metadata-route-handlers#metadata-api)
implementation
* @rylew1 commented we could remove this from each page. To do that we
could use [prop
arguments](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#with-segment-props)
and update the based on the param. There is also more we can do with the
metadata to properly add [app links and twitter
cards](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#applinks).
TODO: create ticket
4. Replace i18n's `useTranslation` with next-intl's `useTranslations`
5. Remove hard-coded strings that were present b/c we were still b/w
i18next and next-intl

* [Move process page to
app](32ba4ee)

* [Move research page to
app](5b5ad1a)

* [Move health page to
app](a3e6255)

* [Move feature flag page to
app](395baed)
* [Move search page to app
router](1e261e3)
* [Move newsletter pages to app
router](b509ef8)
* [Move home page to app
router](de1be98)
* [Move home page to app
router](74077ae)
* [Move 404 page to app
router](ccbc956)

1. [Delete hello
api](5bad6ea)
     * This was left from the project creation
2. [Add USWDS icon
component](0120c7b)
* as noted in a slack discussion, when trying to access [one of the
icons](https://github.com/trussworks/react-uswds/blob/main/src/components/Icon/Icons.ts)
using `<Icon.Search/>` next errors: `You cannot dot into a client module
from a server component. You can only pass the imported name through`.
I'm not sure why it thinks the Icon component is a client module. [Dan
A.
suggests](vercel/next.js#51593 (comment))
trussworks should re-export as named exports. I tried importing the SVGs
directly from the trussworks library but [svgr requires a custom webpack
config](https://react-svgr.com/docs/next/) which is a road I didn't want
to go down and [react svg](https://www.npmjs.com/package/react-svg)
through an error in the app router 😥 .
* I implemented @sawyerh 's
[suggestion](0120c7b#diff-dadb35bd2f3f61f2c179f033cd0a2874fc343974236f2fb8613664703c751429),
which did not work initially b/c next reported the USWDS icon was
corrupt, which was fixed by adding a `viewBox` to the svg element 😮‍💨 .
* [Remove unused
WtGIContent](75490f7)

* [Move layout and update for app
router](af112fd)

* [Update global components for the app
router](40119e6)

* [Move i18n strings for app
router](eb3c07c)

* [Adds next-intl config and removes
i18n](c546571)

* [Update tests for app
router](3b9b193)

* [Removes i18next and next-i18n
packages](9d2e08a)

* [Update storybook settings for app
router](39f115d)
acouch added a commit to navapbc/simpler-grants-gov that referenced this issue Sep 18, 2024
Fixes #6

1. Move all pages to
[`[locale]`](https://next-intl-docs.vercel.app/docs/getting-started/app-router/with-i18n-routing#getting-started)
folder
2. Add
[`generateMetata()`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function)
function and [next-intl
`getTranslations()`](https://next-intl-docs.vercel.app/docs/environments/metadata-route-handlers#metadata-api)
implementation
* @rylew1 commented we could remove this from each page. To do that we
could use [prop
arguments](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#with-segment-props)
and update the based on the param. There is also more we can do with the
metadata to properly add [app links and twitter
cards](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#applinks).
TODO: create ticket
4. Replace i18n's `useTranslation` with next-intl's `useTranslations`
5. Remove hard-coded strings that were present b/c we were still b/w
i18next and next-intl

* [Move process page to
app](32ba4ee)

* [Move research page to
app](5b5ad1a)

* [Move health page to
app](a3e6255)

* [Move feature flag page to
app](395baed)
* [Move search page to app
router](1e261e3)
* [Move newsletter pages to app
router](b509ef8)
* [Move home page to app
router](de1be98)
* [Move home page to app
router](74077ae)
* [Move 404 page to app
router](ccbc956)

1. [Delete hello
api](5bad6ea)
     * This was left from the project creation
2. [Add USWDS icon
component](0120c7b)
* as noted in a slack discussion, when trying to access [one of the
icons](https://github.com/trussworks/react-uswds/blob/main/src/components/Icon/Icons.ts)
using `<Icon.Search/>` next errors: `You cannot dot into a client module
from a server component. You can only pass the imported name through`.
I'm not sure why it thinks the Icon component is a client module. [Dan
A.
suggests](vercel/next.js#51593 (comment))
trussworks should re-export as named exports. I tried importing the SVGs
directly from the trussworks library but [svgr requires a custom webpack
config](https://react-svgr.com/docs/next/) which is a road I didn't want
to go down and [react svg](https://www.npmjs.com/package/react-svg)
through an error in the app router 😥 .
* I implemented @sawyerh 's
[suggestion](0120c7b#diff-dadb35bd2f3f61f2c179f033cd0a2874fc343974236f2fb8613664703c751429),
which did not work initially b/c next reported the USWDS icon was
corrupt, which was fixed by adding a `viewBox` to the svg element 😮‍💨 .
* [Remove unused
WtGIContent](75490f7)

* [Move layout and update for app
router](af112fd)

* [Update global components for the app
router](40119e6)

* [Move i18n strings for app
router](eb3c07c)

* [Adds next-intl config and removes
i18n](c546571)

* [Update tests for app
router](3b9b193)

* [Removes i18next and next-i18n
packages](9d2e08a)

* [Update storybook settings for app
router](39f115d)
acouch added a commit to HHS/simpler-grants-gov that referenced this issue Sep 18, 2024
Fixes #6

1. Move all pages to
[`[locale]`](https://next-intl-docs.vercel.app/docs/getting-started/app-router/with-i18n-routing#getting-started)
folder
2. Add
[`generateMetata()`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function)
function and [next-intl
`getTranslations()`](https://next-intl-docs.vercel.app/docs/environments/metadata-route-handlers#metadata-api)
implementation
* @rylew1 commented we could remove this from each page. To do that we
could use [prop
arguments](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#with-segment-props)
and update the based on the param. There is also more we can do with the
metadata to properly add [app links and twitter
cards](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#applinks).
TODO: create ticket
4. Replace i18n's `useTranslation` with next-intl's `useTranslations`
5. Remove hard-coded strings that were present b/c we were still b/w
i18next and next-intl

* [Move process page to
app](navapbc@32ba4ee)

* [Move research page to
app](navapbc@5b5ad1a)

* [Move health page to
app](navapbc@a3e6255)

* [Move feature flag page to
app](navapbc@395baed)
* [Move search page to app
router](navapbc@1e261e3)
* [Move newsletter pages to app
router](navapbc@b509ef8)
* [Move home page to app
router](navapbc@de1be98)
* [Move home page to app
router](navapbc@74077ae)
* [Move 404 page to app
router](navapbc@ccbc956)

1. [Delete hello
api](navapbc@5bad6ea)
     * This was left from the project creation
2. [Add USWDS icon
component](navapbc@0120c7b)
* as noted in a slack discussion, when trying to access [one of the
icons](https://github.com/trussworks/react-uswds/blob/main/src/components/Icon/Icons.ts)
using `<Icon.Search/>` next errors: `You cannot dot into a client module
from a server component. You can only pass the imported name through`.
I'm not sure why it thinks the Icon component is a client module. [Dan
A.
suggests](vercel/next.js#51593 (comment))
trussworks should re-export as named exports. I tried importing the SVGs
directly from the trussworks library but [svgr requires a custom webpack
config](https://react-svgr.com/docs/next/) which is a road I didn't want
to go down and [react svg](https://www.npmjs.com/package/react-svg)
through an error in the app router 😥 .
* I implemented @sawyerh 's
[suggestion](navapbc@0120c7b#diff-dadb35bd2f3f61f2c179f033cd0a2874fc343974236f2fb8613664703c751429),
which did not work initially b/c next reported the USWDS icon was
corrupt, which was fixed by adding a `viewBox` to the svg element 😮‍💨 .
* [Remove unused
WtGIContent](navapbc@75490f7)

* [Move layout and update for app
router](navapbc@af112fd)

* [Update global components for the app
router](navapbc@40119e6)

* [Move i18n strings for app
router](navapbc@eb3c07c)

* [Adds next-intl config and removes
i18n](navapbc@c546571)

* [Update tests for app
router](navapbc@3b9b193)

* [Removes i18next and next-i18n
packages](navapbc@9d2e08a)

* [Update storybook settings for app
router](navapbc@39f115d)
@grundmanise
Copy link

The same happens if we try to use exported enum + component defined within the same client component file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests