vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.79k stars 26.95k forks source link

Page.tsx with default and named export fails on build (esLint) #53940

Open oliverkidd opened 1 year ago

oliverkidd commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.1.0: Sun Oct  9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000
    Binaries:
      Node: 18.14.0
      npm: 9.3.1
      Yarn: N/A
      pnpm: N/A
    Relevant Packages:
      next: 13.4.14-canary.2
      eslint-config-next: 13.4.13
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.1.6
    Next.js Config:
      output: N/A

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

App Router, ESLint (eslint-config-next), TypeScript (plugin, built-in types)

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

N/a

To Reproduce

Create a page.tsx file in the app dir with a default export for the page, and a named export to represent any util function.

export default function Page() {
return (
// page return
)
}

export function utilHelper(){
return (
// function return
)
}

Describe the Bug

Previously I have been able to have named exports in addition to a default export in my page.tsx files. All of a sudden the above configuration of a page.tsx file now fails on build with the error:

"Type error: Page "pathtopage/page.tsx" does not match the required types of a Next.js Page. "utilHelper" is not a valid Page export field."

As far as the current build of the site running on vercel suggests, and as the docs state, one should be able to export in this way from any file, including page.tsx.

Expected Behavior

no erros when exporting a named function with a default export from a file

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

vercel

jlous commented 11 months ago

This is pretty major - makes it impossible to test such functions without moving them out of their context

sawyerh commented 10 months ago

Would love to see an option to disable or configure this TypeScript plugin feature. My use case: In order to make it easier to render the interface portion of async server components in tests and Storybook, I would like to follow a pattern like below, but this is prevented by this named export issue:

export default async function Controller() {
  const claim = await getExampleData()
  return <View claim={claim} />
}

export function View(props) {
  return <div>{props.claim.id}</div>
}
Type error: Page "src/app/example/page.tsx" does not match the required types of a Next.js Page.
  "View" is not a valid Page export field.

Example test that this pattern would support:

import { View } from "src/app/example/page"

it("passes accessibility scan", () => {
    const { container } = render(<View claim={{ id: "123" }} />)
    const a11y = await axe(container)
    expect(a11y).toHaveNoViolations()
})

Example Storybook story:

import { View } from "src/app/example/page"

const story = {
  component: View,
 args: {
   claim: { id: "123" }
 }
}

Related #56832, #50870

meymeynard commented 9 months ago

Hello. Also experiencing this. Is there any update? Thanks

absolutegravitas commented 8 months ago

Also affected... could you guys have made a more inscrutable error... seriously...

guidocaru commented 8 months ago

Having this problem too

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

DavidCodesDev commented 8 months ago

I'm so close to losing my sh*t with Nextjs

Lsnsh commented 6 months ago
export default function Page() {
  // ...
}

Splitting the non default export from the page file, it works normally.

As for why, it doesn’t seem to be mentioned in the docs.

https://nextjs.org/docs/app/building-your-application/routing/pages

0xFlo commented 6 months ago

Based on the issues you're encountering with Next.js during your build process, it seems you're running into a common problem with Next.js's stricter validation of page exports in version 14. This validation aims to ensure that page files only export React components that are intended to be used as pages, not utility functions or other named exports. You need to tackle this with a precise refactor to align with best practices and address the compilation errors effectively

Understanding the Issue Next.js expects that files under the pages directory (or any file treated as a page component) should only default export a React component that corresponds to a page. If you have other named exports, it can cause the build to fail as Next.js might interpret them as potential page candidates which they are not.

Solution: Restructure Exports and Component Organization To resolve this issue, we need to separate utility functions or non-page components from the page files, ensuring that only the default page export is present in page component files. Here’s how you can adjust your setup:

Separate Utility Functions and Shared Components: Move any named exports that are not page components into separate files within a suitable directory, such as components or utils. Adjust Imports in the Main Page File: Update import statements in your main page files to reflect these changes.

0xFlo commented 6 months ago

see also: https://github.com/vercel/next.js/discussions/56825

confusingbits commented 4 months ago

align with best practices

If this is really the reason, and not a technical requirement, I would strongly encourage that this requirement is removed.

It is not 'best practices' that is literally just an opinion. An equally valid opinion is to prefer locality of behavior, which this rule impairs. React itself pushed back against 'best practices' when it was built, and now think of components as concerns, not technologies. Locality of behavior underlies this concept.

You may disagree, but it's all opinions.

If this export restriction is not a technical requirement, I would prefer to see this error removed.

kika commented 4 months ago

I'm observing this in an unexpected setting: the project has src/app/page.tsx export a default React component and a utility function. Project builds normally. As soon as I add 'use client' to one of the components imported by the page I'm seeing this error. 14.2.4

naingarkar commented 4 months ago

I was also experiencing this kind of error showing

Type error: Page "app/page.tsx" does not match the required types of a Next.js Page.
  "CommentsPage" is not a valid Page export field.

Then I found out it was due to exporting another function inside page.tsx like that

 'use client'
 export function CommentsPage() => {
 }

 export default function Page() => {
      <CommentsPage/>
 }

So, I tried to move that CommentsPage into another file like you did and build then everything fine. And I also found another way of doing it in page.tsx like that by removing export keyword from it.

 'use client'
function CommentsPage() => {
 }

 export default function Page() => {
      <CommentsPage/>
 }
farhan2077 commented 3 months ago

Well, there's more. In /dashboard/[id]/page.tsx, both default export and named exports are present and not causing any build errors. But in /dashboard/[id]/another/page.tsx, both default export and named exports being present is causing errors during building. I'm running next 14.2.3

Sheepeer commented 1 week ago

Well, there's more. In /dashboard/[id]/page.tsx, both default export and named exports are present and not causing any build errors. But in /dashboard/[id]/another/page.tsx, both default export and named exports being present is causing errors during building. I'm running next 14.2.3

same situation. I fixed by using export default function xxxinstead of export default const xxx