在TypeScript中定义React组件的contextTypes的正确方法是什么?

mjo*_*ngr 6 typescript reactjs

如何contextTypes在TypeScript中定义?

我有一个组件(注意:我不确定此问题中详述的必要类型的路由器,但这应该与此无关)

export class Repos extends React.Component<ReposProps, {}> {
    context: {
        router: History
    }

    static contextTypes = {
        router: React.PropTypes.object
    };
Run Code Online (Sandbox Code Playgroud)

它有一个功能

    public handleSubmit(event: React.FormEvent) {
Run Code Online (Sandbox Code Playgroud)

在该函数的末尾,它调用上下文

        this.context.router.push(path);
    }
Run Code Online (Sandbox Code Playgroud)

该组件有一个表单

    public render() {
        return (
            {/* ... */}
                <form onSubmit={this.handleSubmit}>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在this.context.router.push(path);我收到错误"未捕获的TypeError:无法读取未定义的属性'路由器'的错误"编译同样的代码时,我在路由器中使用Repos的文件中收到了TypeScript错误:

ERROR in ./index.tsx
(14,34): error TS2322: Type 'typeof Repos' is not assignable to type 'string | ComponentClass<any> | StatelessComponent<
any>'.
  Type 'typeof Repos' is not assignable to type 'StatelessComponent<any>'.
    Types of property 'contextTypes' are incompatible.
      Type '{ router: Requireable<any>; }' is not assignable to type 'ValidationMap<any>'.
Run Code Online (Sandbox Code Playgroud)

将contextTypes更改为

static contextTypes: React.ValidationMap<any> = {
    router: React.PropTypes.object
};
Run Code Online (Sandbox Code Playgroud)

修复了TypeScript错误,虽然我怀疑这是必要的; 我怀疑是一个不同的问题导致这两个问题.

根据TypeScript问题4785中的讨论:如何在Typescript 1.6中使用React contextTypes?,上面的代码是正确的.如果有帮助,我使用的是TypeScript 1.7.3,React 0.14.7和react-router 2.0.0.

mjo*_*ngr 3

我们在职业生涯中都曾遇到过这个问题。令人惊讶的是我没有注意到这一点。

问题在于thisin的上下文handleSubmit()由于handleSubmit调用方式的不同而不同。更改handleSubmit为粗箭头定义有效:

public handleSubmit = (event: React.FormEvent) => {
Run Code Online (Sandbox Code Playgroud)

在这个特殊情况下,我忽略了这一点,因为我在 TypeScript 世界中并不经常遇到这个问题(我也不经常使用 DOM 元素,并且已经使用 React 不到一周了......没有借口我知道)