Open Thinkscape opened 1 year ago
have you tried export const A
, export const B
, then import * as C
and using them as C.A
, C.B
?
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/next@13.4.7-canary.2_@babel+core@7.22.5_react-dom@18.2.0_react@18.2.0/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 🤷
have you tried
export const A
,export const B
, thenimport * as C
and using them asC.A
,C.B
?
This workaround would work on my own components, but wouldn't for 3rd party packages that use this style of composition...
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.
I had the same problem with antd in app router mode and hope to get it resolved soon.
Have the same problem.
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.
i am having this issue as well
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...
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.
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.
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.
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.
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.)
The same happens if we try to use exported enum + component defined within the same client component file.
Verify canary release
Provide environment information
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
"use client"
clause)dot notation
for composition of several componentsError: Unsupported Server Component type: undefined
Describe the Bug
or
Expected Behavior
Code compiles without fail.
Which browser are you using? (if relevant)
irrelevant
How are you deploying your application? (if relevant)
Vercel