React,Typescript中无状态功能组件内的事件处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React,Typescript中无状态功能组件内的事件处理相关的知识,希望对你有一定的参考价值。

我的一个功能组件中有一个onClick事件:

import * as React from 'react';

const BreadCrumbs: React.SFC<{level: Array<string>, changeLevel: Function}> = ({level, changeLevel}) => {
    return (
      <div>
        {
          level.map(function(elem, i) { 
            return <span key={i} onClick={changeLevel}>{elem}</span> 
          })
        }
      </div>
    )
}

export default BreadCrumbs;

在父组件中,我提供了带有数组道具和函数引用的<BreadCrumbs>组件:

<BreadCrumbs level={this.state.levels} changeLevel={this.changeLevel}/>

这不起作用,因为在<BreadCrumbs>组件中,Typescript编译器失败并出现错误(在return <span>行上):

[ts]
Type '{ key: number; onClick: Function; children: string; }' is not assignable to type 'DetailedhtmlProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>'.
  Type '{ key: number; onClick: Function; children: string; }' is not assignable to type 'HTMLAttributes<HTMLSpanElement>'.
    Types of property 'onClick' are incompatible.
      Type 'Function' is not assignable to type '((event: MouseEvent<HTMLSpanElement>) => void) | undefined'.
        Type 'Function' is not assignable to type '(event: MouseEvent<HTMLSpanElement>) => void'.
          Type 'Function' provides no match for the signature '(event: MouseEvent<HTMLSpanElement>): void'.
(JSX attribute) onClick: Function

但是,如果我将我的代码修改为:

const BreadCrumbs: React.SFC<{level: Array<string>, changeLevel: Function}> = ({level, changeLevel}) => {
    function something(i: number) {
      changeLevel(i);
    }
    return (
      <div>
        {
          level.map(function(elem, i) { 
            return <span key={i} onClick={something.bind(this, i)}>{elem}</span> 
          })
        }
      </div>
    )
}

export default BreadCrumbs;

一切正常。为什么第一个版本不起作用?

答案

在TypeScript中,它使用强类型方式对函数执行类型检查,这会考虑函数的参数和返回值。因此,对于参数(React component prop)changeLevel,其类型应声明为(event: React.MouseEvent<HTMLSpanElement>) => void或兼容类型(如(e: React.MouseEvent<Element>) => void() => void() => any)。 Function类型不用于函数类型声明,而是用于键入任何函数对象的全局构造函数,它缺少有关函数对象的信息,在键入函数时应该避免。

您可以将代码更改为以下版本以传递TypeScript的检查。

const BreadCrumbs: React.SFC<{level: Array<string>, changeLevel: () => void}> = ({level, changeLevel}) => {
    return (
      <div>
        {
          level.map(function(elem, i) { 
            return <span key={i} onClick={changeLevel}>{elem}</span> 
          })
        }
      </div>
    )
}

实际上,在第二个版本中,bind函数的返回类型是any,可以将其分配给TypeScript中任何类型的变量。 TypeScript在该版本中不执行任何类型检查。

以上是关于React,Typescript中无状态功能组件内的事件处理的主要内容,如果未能解决你的问题,请参考以下文章

[react] 在react中无状态组件有什么运用场景

如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?

Typescript - React 0.14 无状态功能组件

如何在 React Native 的无状态功能组件中扩展原生组件的 props TypeScript 接口?

如何在带有 TypeScript 的 React-Native 中使用 styled-component 键入无状态功能组件?

React - useRef 与 TypeScript 和功能组件