definitelytyped - Bruke getInitialProps i Next.js med TypeScript


Fra dokumentasjonen, kunngjøringen av Next.js 5.0 og ulike artikler på internett ser det ut til at Next.js støtter TypeScript godt og at mange bruker det.

Men disse trådene antyder at getInitialProps, som er avgjørende for Next.js-apper, ikke fungerer:

  • https://github.com/zeit/next.js/issues/3396
  • https://github.com/zeit/next.js/issues/1651
  • https://github.com/DefinitelyTyped/DefinitelyTyped/issues/23356

Hvordan kan jeg fikse det? Både i klasse- og funksjonskomponenter, når jeg gjør ComponentName.getInitialProps=async function() {...} får jeg følgende feil:

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

Svar #1

Rediger 2021/04/23: Svaret mitt nedenfor er også utdatert

Vennligst se Next.js-dokumentasjonen for den nåværende anbefalingen for typifisering av metoder for datainnhenting ved bruk av nye typer og navngitte eksport.

kort fortalt:

import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'

export const getStaticProps: GetStaticProps = async (context) => {
  // ...
}

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

export const getServerSideProps: GetServerSideProps = async (context) => {
  // ...
}


Utdatert (men funksjonell) svar:

De ovennevnte svarene er utdaterte siden Next.js nå offisielt støtter TypeScript (kunngjøring her)

En del av denne utgivelsen er bedre TypeScript-typer, med mye av Next.js skrevet i TypeScript selv. Dette betyr at @types/next-pakken vil bli avviklet til fordel for de offisielle Next.js-typene.

I stedet bør du importere typen NextPage og tilordne den til komponenten din. Du kan også type getInitialProps ved å bruke typen 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
}

Svar #2

REDIGER: dette svaret er utdatert siden utgivelsen av Next 9. Se svaret ovenfor.

Den klassiske måten å løse problemet på er å erklære getInitialProps som et statisk medlem:

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

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

  render() {...}

}

Når du jobber med statsløse komponenter, kan du erklære en enkel utvidelse av React.SFC:

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

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

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

Svar #3

Typer for Next.js vedlikeholdes i DefinitelyTyped-prosjektet, som har en ny versjon 7.0.6.

For å bruke de nye typene, sørg for at du importerer dem i prosjektet ditt:

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

Slik skriver du getInitialProps for en statsløs funksjonell komponent:

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

Slik skriver du getInitialProps for en klasse:

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

Hvis du ser gjennom testene i DefinitelyTyped, kan du få mye innsikt i hvordan du bruker andre varianter av typene for Next.

Relaterte artikler