web-dev-qa-db-ja.com

TypeScriptでNext.jsのgetInitialPropsを使用する

ドキュメント、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'.
12
lukas

編集:この回答は、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) => {...}
22
Mikael Couzic

Next.jsがTypeScriptを公式にサポートするようになったため、上記の回答は古くなっています(お知らせ here

このリリースの一部はより優れたTypeScript型であり、Next.jsの多くはTypeScript自体で記述されています。これは、@types/nextパッケージは、公式のNext.jsタイピングを支持して廃止されます。

代わりに、 NextPage type をインポートして、コンポーネントに割り当てる必要があります。 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
}

9

Next.jsのタイプは、新しいバージョン7.0.6を持つ DefinitelyTypedプロジェクト で維持されます。

新しいタイプを使用するには、プロジェクトにインポートしていることを確認してください。

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

ステートレス機能コンポーネントに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

DefinitelyTypedのテスト を確認すると、Nextの入力の他のバリエーションの使用方法に関する多くの洞察を得ることができます。

8
Justin Noel