在 Next.js 中使用 getInitialProps 和 TypeScript

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49929268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:22:12  来源:igfitidea点击:

Using getInitialProps in Next.js with TypeScript

typescriptdefinitelytypednextjs

提问by lukas

From the documentation, Next.js 5.0 announcement and various articles around on the internet it seems like Next.js supports TypeScript well and many people are using it.

从文档、Next.js 5.0 公告和互联网上的各种文章来看,Next.js 似乎很好地支持 TypeScript,并且很多人都在使用它。

But these threads suggest that getInitialProps, which is vital to Next.js apps, doesn't work:

但是这些线程表明,getInitialProps对 Next.js 应用程序至关重要的 不起作用:

How can I fix it? In both class and functional components, when I do ComponentName.getInitialProps = async function() {...}I get the following error:

我该如何解决?在类和功能组件中,当我这样做时,ComponentName.getInitialProps = async function() {...}我收到以下错误:

[ts] Property 'getInitialProps' does not exist on type '({ data }: { data: any; }) => Element'.

回答by James Mulholland

The above answers are out of date since Next.js now officially supports TypeScript (announcement here)

以上答案已过时,因为 Next.js 现在正式支持 TypeScript(此处公告)

Part of this release is better TypeScript types, with much of Next.js being written in TypeScript itself. This means that the @types/nextpackage will be deprecated in favour of the official Next.js typings.

此版本的一部分是更好的 TypeScript 类型,其中大部分 Next.js 都是用 TypeScript 本身编写的。这意味着该@types/next包将被弃用,以支持官方 Next.js 类型。

Instead, you should import the NextPagetypeand assign that to your component. You can also type getInitialPropsusing the NextPageContexttype.

相反,您应该导入NextPage类型并将其分配给您的组件。您也可以getInitialProps使用类型进行NextPageContext输入。

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
}

回答by Mikael Couzic

EDIT: this answer is out of date since the release of Next 9. See answer above.

编辑:自 Next 9 发布以来,此答案已过时。请参阅上面的答案。

The classical way to solve the problem is to declare getInitialPropsas a static member:

解决问题的经典方法是声明getInitialProps为静态成员:

class MyComponent extends React.Component<{...}, {}> {

  static async getInitialProps(ctx: any) {
    return {...}
  }

  render() {...}

}

When working with stateless components, you can declare a simple extension of React.SFC:

使用无状态组件时,您可以声明一个简单的扩展React.SFC

interface StatelessPage<P = {}> extends React.SFC<P> {
  getInitialProps?: (ctx: any) => Promise<P>
}

const MyComponent: StatelessPage<{...}> = (...) => ...

MyComponent.getInitialProps = async (ctx) => {...}

回答by Justin Noel

Types for Next.js are maintained in the DefinitelyTyped projectwhich has a new version 7.0.6.

Next.js 的类型在有新版本 7.0.6的绝对类型项目中维护。

In order to use the new types, make sure you are importing them in your project:

为了使用新类型,请确保在项目中导入它们:

npm install --save-dev @types/[email protected]

Here is how you type getInitialPropsfor a stateless functional component:

以下是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

Here is how you type getInitialPropsfor a class:

以下是您键入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

If you review the tests in DefinitelyTyped, you can get a lot of insights on how to use other variations of the typings for Next.

如果您查看IndeedTyped 中测试,您可以获得很多关于如何使用 Next 类型的其他变体的见解。

回答by arnaudjnn

Following the documentation

按照文档

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