我正在自学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,但是当我尝试使用“
请原谅我的代码段和React标记中的空格错误。我不知道如何在不增加额外空格的情况下显示它们,而且我几乎完全可以确定这不是语法错误,但可以的话,请随时证明我是错误的。
答案 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的情况,似乎它没有包装在函数中。它接受索引号,然后返回为该单击处理程序存储的另一个函数。调用任何事件时,它们都会在其范围内保留索引值的副本,以便您可以访问它。