next.js icon indicating copy to clipboard operation
next.js copied to clipboard

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

Open oliverkidd opened this issue 2 years ago • 14 comments

Verify canary release

  • [X] I verified that the issue exists in the latest Next.js 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

oliverkidd avatar Aug 12 '23 07:08 oliverkidd

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

jlous avatar Nov 14 '23 16:11 jlous

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

sawyerh avatar Dec 15 '23 00:12 sawyerh

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

meymeynard avatar Feb 07 '24 05:02 meymeynard

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

absolutegravitas avatar Feb 27 '24 13:02 absolutegravitas

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!

guidocaru avatar Mar 07 '24 04:03 guidocaru

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

DavidCodesDev avatar Mar 09 '24 15:03 DavidCodesDev

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

Lsnsh avatar May 07 '24 09:05 Lsnsh

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 avatar May 07 '24 22:05 0xFlo

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

0xFlo avatar May 07 '24 22:05 0xFlo

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.

confusingbits avatar Jun 12 '24 15:06 confusingbits

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

kika avatar Jun 22 '24 22:06 kika

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/>
}

naingarkar avatar Jun 27 '24 06:06 naingarkar

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

farhan2077 avatar Jul 26 '24 14:07 farhan2077

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 xxx instead of export default const xxx

MattinaYang avatar Oct 24 '24 07:10 MattinaYang

I have the same problem. I still haven't resolved it.

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!

frankiefab100 avatar Jan 10 '25 14:01 frankiefab100