在带有 TypeScript 的 Next.js 中使用 getInitialProps
Posted
技术标签:
【中文标题】在带有 TypeScript 的 Next.js 中使用 getInitialProps【英文标题】:Using getInitialProps in Next.js with TypeScript 【发布时间】:2018-09-30 10:34:35 【问题描述】:从文档、Next.js 5.0 公告和互联网上的各种文章来看,Next.js 似乎很好地支持 TypeScript,并且很多人都在使用它。
但这些线程表明对 Next.js 应用程序至关重要的 getInitialProps
不起作用:
我该如何解决?在类和功能组件中,当我执行 ComponentName.getInitialProps = async function() ...
时,我收到以下错误:
[ts] Property 'getInitialProps' does not exist on type '( data : data: any; ) => Element'.
【问题讨论】:
【参考方案1】:编辑 2021/04/23:我下面的答案也已过时
请参阅the Next.js docs,了解有关使用新类型和命名导出键入数据获取方法的当前建议。
tl;博士:
import GetStaticProps, GetStaticPaths, GetServerSideProps from 'next'
export const getStaticProps: GetStaticProps = async (context) =>
// ...
export const getStaticPaths: GetStaticPaths = async () =>
// ...
export const getServerSideProps: GetServerSideProps = async (context) =>
// ...
过时(但功能正常)的答案:
由于Next.js现在正式支持TypeScript,以上答案已经过时(公告here)
此版本的一部分是更好的 TypeScript 类型,Next.js 的大部分内容都是用 TypeScript 本身编写的。这意味着 @types/next
包将被弃用,取而代之的是官方的 Next.js 类型。
相反,您应该导入 NextPage
type 并将其分配给您的组件。您也可以使用NextPageContext
类型键入getInitialProps
。
import NextPage, NextPageContext from 'next';
const MyComponent: NextPage<MyPropsInterface> = props => (
// ...
)
interface Context extends NextPageContext
// any modifications to the default context, e.g. query types
MyComponent.getInitialProps = async (ctx: Context) =>
// ...
return props
【讨论】:
对于非页面的组件会是什么样子? @Alp 非页面组件不能使用getInitialProps
。因此,您只需像普通的反应组件一样输入它(一些道具接口,推断的返回类型是我最喜欢的。您也可以使用React.FunctionComponent
)
谢谢。 “一些道具接口,推断的返回类型是我最喜欢的” - 你能详细说明一下吗?不知道会是什么样子。
@Alp interface Props propName: string; ; const MyComponent = (props: Props) => ( /* ... */ )
有谁知道如何修复@typescript-eslint/unbound-method
?它在MyComponent.getInitialProps = ...
中突出显示MyComponent
【参考方案2】:
编辑:自 Next 9 发布以来,此答案已过时。请参阅上面的答案。
解决问题的经典方法是将getInitialProps
声明为静态成员:
class MyComponent extends React.Component<..., >
static async getInitialProps(ctx: any)
return ...
render() ...
在使用无状态组件时,可以声明React.SFC
的简单扩展:
interface StatelessPage<P = > extends React.SFC<P>
getInitialProps?: (ctx: any) => Promise<P>
const MyComponent: StatelessPage<...> = (...) => ...
MyComponent.getInitialProps = async (ctx) => ...
【讨论】:
虽然可用,但自 Next 9 发布以来,此答案已过时。请参阅下面有关如何使用官方 Next.js 分型的我的答案【参考方案3】:Next.js 的类型在 DefinitelyTyped project 中维护,它有一个新版本 7.0.6。
要使用新类型,请确保将它们导入项目中:
npm install --save-dev @types/next@7.0.6
这是您为无状态功能组件键入getInitialProps
的方式:
import NextFunctionComponent, NextContext from 'next'
// Define what an individual item looks like
interface IDataObject
id: number,
name: string
// Define the props that getInitialProps will inject into the component
interface IListComponentProps
items: IDataObject[]
const List: NextFunctionComponent<IListComponentProps> = ( items ) => (
<ul>
items.map((item) => (
<li key=item.id>
item.id -- item.name
</li>
))
</ul>
)
List.getInitialProps = async ( pathname : NextContext) =>
const dataArray: IDataObject[] =
[ id: 101, name: 'larry' , id: 102, name: 'sam' , id: 103, name: 'jill' , id: 104, name: pathname ]
return items: dataArray
export default List
以下是您为课程键入getInitialProps
的方式:
import React from 'react'
import NextContext from 'next'
// Define what an individual item looks like
interface IDataObject
id: number,
name: string
// Define the props that getInitialProps will inject into the component
interface IListClassProps
items: IDataObject[]
class List extends React.Component<IListClassProps>
static async getInitialProps( pathname : NextContext)
const dataArray: IDataObject[] =
[ id: 101, name: 'larry' , id: 102, name: 'sam' , id: 103, name: 'jill' , id: 104, name: pathname ]
return items: dataArray
render()
return (
<ul>
this.props.items.map((item) => (
<li key=item.id>
item.id -- item.name
</li>
))
</ul>
)
export default List
如果您查看tests in DefinitelyTyped,您可以深入了解如何为 Next 使用其他类型的类型。
【讨论】:
虽然不错,但自 Next 9 发布以来,此答案已过时。请参阅下面的答案【参考方案4】:遵循文档
import React from 'react'
import NextPageContext from 'next'
interface Props
userAgent?: string;
export default class Page extends React.Component<Props>
static async getInitialProps( req : NextPageContext)
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
return userAgent
render()
const userAgent = this.props
return <main>Your user agent: userAgent</main>
【讨论】:
【参考方案5】:简单的解决方案是声明类型:
declare global
namespace React
interface FunctionComponent<P = >
getInitialProps(): void;
【讨论】:
以上是关于在带有 TypeScript 的 Next.js 中使用 getInitialProps的主要内容,如果未能解决你的问题,请参考以下文章
Next.js:在 getServerSideProps 中使用带有 TypeScript 的 next-redux-wrapper 调用 Thunks?
在带有 TypeScript 的 next.js 中使用 Router 的空安全方式
使用带有 TypeScript 的 next/image 时获取主机未配置错误
暗模式在带有 Nextjs 和 Typescript 的 Tailwind CSS V3 中不起作用