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

Why does JavaScript's map() work but my for loop fails with React?

我正在自学 React,但遇到了一些我难以理解的事情。当我使用下面的 getNavList() 中的代码构建我的项目时,单击我的组件中呈现的按钮之一时出现以下错误,"cannot read property of undefined 'click' react."

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 对象的函数绑定到其父 class 中,但无济于事。我还尝试使用箭头符号定义函数,但没有成功。话虽这么说,为什么这种从 for 循环到 map 函数的更改有效?

同一代码段中还有一个更小的问题。使用工作 getNavList() 我 return a React.Fragment 使用 shorthand 语法“< >...< />”但是当我尝试使用“< React.Fragment>. ..< /React.Fragment>" 我收到一条错误消息,指出在我的 else 语句末尾有一个预期的 '}' 字符。这到底是怎么回事?

请原谅我的代码片段和 React 标签中的空格错误。我无法弄清楚如何在不添加额外空格的情况下让它们显示,我几乎完全确定这不是语法错误,但如果是这种情况,请随时证明我错了。

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

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

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

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

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

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

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

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