簡體   English   中英

在 Next.js 和 TypeScript 中使用 getInitialProps

[英]Using getInitialProps in Next.js with TypeScript

從文檔來看,Next.js 5.0 公告和互聯網上的各種文章似乎 Next.js 很好地支持 TypeScript 並且很多人都在使用它。

但是這些線程表明getInitialProps對 Next.js 應用程序至關重要,它不起作用:

我該如何解決? 在 class 和功能組件中,當我執行ComponentName.getInitialProps = async function() {...}時,我收到以下錯誤:

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

編輯 2021/04/23:我下面的回答也已過時

有關使用新類型和命名導出鍵入數據獲取方法的當前建議,請參閱Next.js 文檔

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( 此處公告)

此版本的一部分是更好的 TypeScript 類型,其中大部分 Next.js 都是用 TypeScript 本身編寫的。 這意味着@types/next包將被棄用,取而代之的是官方 Next.js 類型。

相反,您應該導入NextPage類型並將其分配給您的組件。 您還可以使用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
}

編輯:自 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.js 的類型在有新版本 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

如果您查看DescribeTyped 中測試,您可以獲得很多關於如何使用 Next 類型的其他變體的見解。

按照文檔

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

簡單的解決方案是聲明類型:

declare global {
   namespace React {
      interface FunctionComponent<P = {}> {
      getInitialProps(): void;
}}}

如果您使用 TypeScript,您可以對 function 組件使用 NextPage 類型

Nextjs 文檔

它不是一個真正的解決方案,但可能的解決方法是僅將TypeScript用於服務器端和通用腳本(.ts擴展名)。

對於React組件,請使用.jsx擴展名並放棄TypeScript。 prop-typesprop-types-exact - 它們為props提供類型檢查(使用npm安裝包)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM