反应在onClick中处理

时间:2019-07-19 18:29:00

标签: reactjs typescript

我想通过以下组件控制我的react-router:

import React from 'react';

export interface INavigationMenuProps{
   routes: string[];
}

export class NavigationMenu extends React.Component<INavigationMenuProps> {

    constructor(props: INavigationMenuProps) {
        super(props);

    }

    handleButtonClick(path: string) : void {
        //this.props.history.replace(path);
        console.log(path);
    }

    render() {
        let self = this; 
        return (
            <div>   
            {
                this.props.routes.map(function(item,id) {
                    let buttonText = item.replace('/','');
                    return <button key={id} onClick={ (e) => {self.handleButtonClick(item);}}>{buttonText}</button>
                })
            }   
            </div>
        )
    }
}

这确实有效。但是看着渲染功能让我思考这是否是一个合适的解决方案。我必须将this安全地保存到变量,然后将lambda函数传递给按钮的on-click-handler,该按钮会调用我的this变量的handleButtonClick-function。

这真的是处理事件的正确方法吗?

我也尝试过:

return <button key={id} onClick={this.handleButtonClick(item)}>{buttonText}</button>

但是这不起作用,因为onClickhandleButtonClick的签名不同

所以我不得不包装函数调用并尝试这样做:

return <button key={id} onClick={()=> {this.handleButtonClick(item);}}>{buttonText}</button>

但是随后出现以下错误:

  

'this'隐式具有类型'any',因为它没有类型   注释

  1. 有人可以解释为什么我将其存储到变量中时会起作用吗?
  2. 这真的是方法吗?

2 个答案:

答案 0 :(得分:2)

关于行let self = this;,React代码库中最常见的方法是将这些函数绑定到组件的构造函数中。因此,您需要在构造函数的末尾添加一行如下代码:

this.handleButtonClick = this.handleButtonClick.bind(this);

在这种情况下,您不应遇到该“隐含任何”错误。该模式对于将功能绑定到组件的实例是必需的,这是您在运行时通过将this分配给self在render()中执行的操作。 / p>

要回答您的编号问题: 1.我的猜测是TypeScript能够解析变量的类型,但无法将this解析为类NavigationMenu的实例。 2.是的。此处的总体模式是正确的(在组件中编写单击处理程序以处理您可能需要的任何自定义逻辑)。我通常在React代码中看到这种情况,然后自己写React。您偏离我通常看到的地方的地方不是在构造函数中绑定函数。

答案 1 :(得分:1)

@ michael-langan的回答是正确的,但只是为了“完整”并提出另一种解决方案...您也可以采用这种方法(@tmeans在他的评论中暗示...):

import React from 'react';

export interface INavigationMenuProps{
  routes: string[];
}

export class NavigationMenu extends React.Component<INavigationMenuProps> {

  constructor(props: INavigationMenuProps) {
    super(props);
  }

  handleButtonClick = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => {
    const path = event.currentTarget.getAttribute('data-route');
    console.log(path);
    this.props.history.replace(path);
  }

  render() { 
    return (
        <div>   
        {
            this.props.routes.map((item, id) => {
                let buttonText = item.replace('/','');
                return <button key={id} data-route={item} onClick={this.handleButtonClick }>{buttonText}</button>
            })
        }   
        </div>
    )
  }
}

此方法的优点之一是,它避免在Component的点击处理程序内创建箭头函数,由于每次React渲染时都会“重新创建”此函数,因此有时可能会导致性能问题

此外,这避免了在构造函数中进行绑定,如果您在同一Component中有很多单击处理程序,则有时可能会造成阅读混乱。

但是,所有这些实际上都取决于首选项以及您严格遵循的规则。就像我说的那样,@ michael-langan的答案也完全正确。