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

7

如何在TypeScript中定义contextTypes

我有一个组件(注意:详见这个问题,但这在此处并不相关)。

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

    static contextTypes = {
        router: React.PropTypes.object
    };

它具备一个功能。
    public handleSubmit(event: React.FormEvent) {

在该函数的结尾处,它调用了上下文。
        this.context.router.push(path);
    }

该组件具有表单功能。
    public render() {
        return (
            {/* ... */}
                <form onSubmit={this.handleSubmit}>
        );
    }
}

然而,在this.context.router.push(path);这行代码上,我收到了错误消息"Uncaught TypeError: Cannot read property 'router' of undefined"。当编译这段代码时,我在使用 Repos in a Router 的文件中收到了 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>'.

将contextTypes更改为

static contextTypes: React.ValidationMap<any> = {
    router: React.PropTypes.object
};

我修复了TypeScript错误,尽管我怀疑这是不必要的;我怀疑另一个问题是导致这两个问题的原因。

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


如果你分享代码,我可以看一下。 我个人还没有使用过 contextrouter :) - basarat
链接到特定的提交,其中出现了问题 -- 这个可以使用TypeScript 1.7.3编译,但我刚刚注意到1.8.2破坏了它。运行npm start,在浏览器中输入localhost:8080/repos,输入两个文本字段并按Go键,就会看到Router未定义的错误发生。 - mejdev
我使用临时解决方案更新了该存储库,以解决TS 1.8.2编译问题。 - mejdev
1
哇,我真是个白痴。问题在于绑定这个东西。我不知道现在是否适合保留这个问题或者删除它。 - mejdev
1个回答

3
我们在职业生涯中都曾遇到过这个问题。令人惊讶的是我没有发现这个问题。
问题出在handleSubmit()this的上下文被改变了,因为handleSubmit的调用方式不同。将handleSubmit更改为一个箭头函数定义即可解决:
public handleSubmit = (event: React.FormEvent) => {

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接