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

Add error when GSSP methods are added as page component members #11645

Merged
merged 1 commit into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions errors/gssp-component-member.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# getStaticProps/getServerProps can not be attached to the page component

#### Why This Error Occurred

On one of your page's components you attached either `getStaticProps`, `getStaticPaths`, or `getServerSideProps` as a member instead of as a separate export.

These methods can not be attached in the same way as `getInitialProps` and must be their own export

#### Possible Ways to Fix It

Move the method to it's own export from your page.

**Before**

```jsx
function Page(props) {
return <p>hello world</p>
}

Page.getStaticProps = () => ({
props: {
hello: 'world',
},
})

export default Page
```

**After**

```jsx
function Page(props) {
return <p>hello world</p>
}

export default Page

export const getStaticProps = () => ({
props: {
hello: 'world',
},
})
```

### Useful Links

- [Data Fetching Docs](https://nextjs.org/docs/basic-features/data-fetching)
2 changes: 2 additions & 0 deletions packages/next/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ export const UNSTABLE_REVALIDATE_RENAME_ERROR =
'To try the experimental implementation, please use `unstable_revalidate` instead.\n' +
"We're excited for you to try this feature—please share all feedback on the RFC:\n" +
'https://nextjs.link/issg'

export const GSSP_COMPONENT_MEMBER_ERROR = `can not be attached to a page's component and must be exported from the page. See more info here: https://err.sh/next.js/gssp-component-member`
13 changes: 13 additions & 0 deletions packages/next/next-server/server/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
SERVER_PROPS_SSG_CONFLICT,
SSG_GET_INITIAL_PROPS_CONFLICT,
UNSTABLE_REVALIDATE_RENAME_ERROR,
GSSP_COMPONENT_MEMBER_ERROR,
} from '../../lib/constants'
import { isSerializableProps } from '../../lib/is-serializable-props'
import { isInAmpMode } from '../lib/amp'
Expand Down Expand Up @@ -349,6 +350,18 @@ export async function renderToHTML(
!isSSG &&
!getServerSideProps

for (const methodName of [
'getStaticProps',
'getServerSideProps',
'getStaticPaths',
]) {
if ((Component as any)[methodName]) {
throw new Error(
`page ${pathname} ${methodName} ${GSSP_COMPONENT_MEMBER_ERROR}`
)
}
}

if (
process.env.NODE_ENV !== 'production' &&
(isAutoExport || isFallback) &&
Expand Down
2 changes: 2 additions & 0 deletions test/integration/ssg-component-members-error/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const Page = () => 'hi'
export default Page
106 changes: 106 additions & 0 deletions test/integration/ssg-component-members-error/test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* eslint-env jest */
/* global jasmine */
import fs from 'fs-extra'
import { join } from 'path'
import {
nextBuild,
launchApp,
findPort,
renderViaHTTP,
killApp,
} from 'next-test-utils'

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2

const appDir = join(__dirname, '..')
const indexPage = join(appDir, 'pages/index.js')
let app
let appPort
let origIndexPage = ''

const runTests = (isDev = false) => {
const getStderr = async () => {
if (isDev) {
let stderr = ''
appPort = await findPort()
app = await launchApp(appDir, appPort, {
onStderr(msg) {
stderr += msg || ''
},
})
await renderViaHTTP(appPort, '/')
await killApp(app)
return stderr
} else {
const { stderr } = await nextBuild(appDir, undefined, { stderr: true })
return stderr
}
}

it('should show error for getStaticProps as component member', async () => {
await fs.writeFile(
indexPage,
`
const Page = () => 'hi'
Page.getStaticProps = () => ({ props: { hello: 'world' }})
export default Page
`
)
expect(await getStderr()).toContain(
`getStaticProps can not be attached to a page's component and must be exported from the page`
)
})

it('should show error for getServerSideProps as component member', async () => {
await fs.writeFile(
indexPage,
`
import React from 'react'
export default class MyPage extends React.Component {
static async getServerSideProps() {
return {
props: {
hello: 'world'
}
}
}
render() {
return 'hi'
}
}
`
)
expect(await getStderr()).toContain(
`getServerSideProps can not be attached to a page's component and must be exported from the page`
)
})

it('should show error for getStaticPaths as component member', async () => {
await fs.writeFile(
indexPage,
`
const Page = () => 'hi'
Page.getStaticPaths = () => ({ paths: [], fallback: true })
export default Page
`
)
expect(await getStderr()).toContain(
`getStaticPaths can not be attached to a page's component and must be exported from the page`
)
})
}

describe('GSSP Page Component Member Error', () => {
beforeAll(async () => {
origIndexPage = await fs.readFile(indexPage, 'utf8')
})
afterAll(() => fs.writeFile(indexPage, origIndexPage))

describe('dev mode', () => {
runTests(true)
})

describe('production mode', () => {
runTests()
})
})