从文档,Next.js 5.0公告和互联网上的各种文章看来,Next.js很好地支持TypeScript,很多人都在使用它。
但是这些主题表明getInitialProps
对Next.js应用程序至关重要,但不起作用:
我该如何解决?在类和功能组件中,当我ComponentName.getInitialProps = async function() {...}
时,我收到以下错误:
[ts] Property 'getInitialProps' does not exist on type '({ data }: { data: any; }) => Element'.
答案 0 :(得分:25)
自从Next.js现在正式支持TypeScript(公告here)以来,上述答案已经过时了
此发行版的一部分是更好的TypeScript类型,其中许多Next.js都是用TypeScript本身编写的。这意味着set
包将被弃用,而支持Next.js的官方输入。
相反,您应该导入NextPage
type并将其分配给您的组件。您也可以使用@types/next
类型输入getInitialProps
。
NextPageContext
答案 1 :(得分:17)
解决问题的经典方法是将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) => {...}
答案 2 :(得分:6)
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中使用其他类型的输入的见解。
答案 3 :(得分:0)
遵循文档
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>
}
}
答案 4 :(得分:0)
简单的解决方案是声明类型:
declare global {
namespace React {
interface FunctionComponent<P = {}> {
getInitialProps(): void;
}}}
答案 5 :(得分:-6)
这不是一个真正的解决方案,但可能的解决方法是仅将TypeScript用于服务器端和通用脚本(.ts扩展名)。
对于React组件,请使用.jsx扩展名并放弃TypeScript。可以使用prop-types
和prop-types-exact
- 它们会对道具进行类型检查(使用npm
安装包)。