为什么JavaScript的map()可以工作,但是我的for循环因React而失败?

时间:2018-11-05 20:46:54

标签: javascript arrays reactjs this react-fullstack

我正在自学React,遇到一些我难以理解的东西。当我使用下面的getNavList()中的代码构建项目时,单击组件中呈现的按钮之一会收到以下错误,“无法读取未定义'click'的属性作出反应。”

export class Pane extends React.Component {
  constructor(props) {
    super(props);

  }

  getNavList() {
    var buttons = [];
    if(this.props.subNavButtons != null){
      for(var i = 0; i < this.props.navButtons.length; i++) {
        buttons.push(<Button onClick={this.props.navButtons[i].click()} title={this.props.navButtons[i].title} />);
        buttons.push(<Button onClick={this.props.navButtons[i + i].click()} title={this.props.navButtons[i + i].title} />);
        buttons.push(<Button onClick={this.props.navButtons[i + i + 1].click()} title={this.props.navButtons[i + i + 1].title} />);
      }
    } else {
      buttons = this.props.navButtons.map(button => (<Button onClick={() => button.click()} title={button.title}/>));
    }
    return buttons;
  }

  render() {
    return (
      <div>
        <ul>
          {this.getNavList()}
        </ul>
      </div>
    );
  }
}

当我通过以下更改构建项目时,一切都会按预期进行:

export class Pane extends React.Component {
      constructor(props) {
        super(props);

      }

      getNavList() {
        var buttons = [];
        if(this.props.subNavButtons != null){
          buttons = this.props.navButtons.map((button, index) => (<>
                                                                  <Button onClick={() => button.click()} title={button.title}/>
                                                                  <Button onClick={() => this.props.subNavButtons[index + index].click()} title={this.props.subNavButtons[index + index].title}/>
                                                                  <Button onClick={() => this.props.subNavButtons[index + index + 1].click()} title={this.props.subNavButtons[index + index + 1].title}/>
                                                                  </>));
        }
        else {
          buttons = this.props.navButtons.map(button => (<Button onClick={() => button.click()} title={button.title}/>));
        }
        return buttons;
      }

      render() {
        return (
          <div>
            <ul>
              {this.getNavList()}
            </ul>
          </div>
        );
      }
    }

根据我的发现,当我将函数作为组件属性传递时,似乎有一个“ this”失去上下文的问题。我试图将传递给其父类中Pane对象的函数绑定无济于事。我也尝试使用箭头符号定义函数,但是没有运气。话虽这么说,为什么从for循环到map函数的这种改变有效呢?

在同一代码段中,这是一个较小的问题。使用正常工作的getNavList(),我使用简写语法“ <> ... ”返回一个React.Fragment,但是当我尝试使用“ ... ”时,我得到一个错误,说我的else语句末尾有一个预期的'}'字符。这到底是怎么回事?

请原谅我的代码段和React标记中的空格错误。我不知道如何在不增加额外空格的情况下显示它们,而且我几乎完全可以确定这不是语法错误,但可以的话,请随时证明我是错误的。

1 个答案:

答案 0 :(得分:0)

  

onClick = {this.props.navButtons [i] .click()}

在第一次单击事件中,react是在安装组件时评估属性。这导致.click()被立即调用。有两种方法可以解决此问题。一种方法是放下括号,这样您就不会立即.click执行点击处理程序。另一个选择是让点击处理程序返回另一个函数(请参见最后的示例)。

  

onClick = {()=> button.click()} title = {button.title}

第二次尝试时,您传入一个匿名方法,该方法调用您的.click()。在这种情况下,react会评估作为函数的值,然后将其保存。事件触发后,React然后将调用此函数。

奖励积分!有时,您想要一个值(如循环中的索引),该值可在点击处理程序中使用。但是,当您触发事件时,它具有错误的值。您可以通过调用返回函数的函数来解决此问题。然后,它将允许您适当地确定该值的范围,以便在需要时就可以使用它。

myThings.map((x, i) => <thing onClick={this.handleClick(i)} />

handleClick = (index: number) => () => {
   alert(index);
}

在此示例中发生的是在装入时执行handleClick的情况,似乎它没有包装在函数中。它接受索引号,然后返回为该单击处理程序存储的另一个函数。调用任何事件时,它们都会在其范围内保留索引值的副本,以便您可以访问它。