这是我的第一个React App([email protected])。我试图找出为什么在使用基于功能的组件与基于类的组件时,onClick事件的处理方式不同。
据我所知,我应该使用基于类的c。只有当我需要改变状态时,我是对的吗?
基于功能的组件抛出_this is undefined error
但基于类 - 不是。
我在两种情况下都使用箭头函数而不是绑定函数。
功能为主:
import React from 'react';
const AnswersDisplay = (props) => {
// even with bind I still get "_this is undefined"
//this.onAnswer = this.onAnswer.bind(this);
const answerList = props.answerList.map( (option) => {
return (
<button
onClick={this.onAnswer}
value={option}
className="ui basic green button">{option}
</button>
)
});
const onAnswer = (e) =>{
console.log(e.target.value);
}
return(
<div className="ui two buttons hSpace">{this.answerList}</div>
);
};
export default AnswersDisplay;
vs基于类的工作。
import React from 'react';
class AnswersDisplay extends React.Component {
constructor(props) {
super(props);
//this.onAnswer = this.onAnswer.bind(this);
}
answerList = this.props.answerList.map( (option) => {
return (
<button
onClick={this.onAnswer}
value={option}
className="ui basic green button">{option}
</button>
)
});
onAnswer = (e) =>{
console.log(e.target.value);
}
render() {
return(
<div className="ui two buttons hSpace">{this.answerList}</div>
);
}
};
export default AnswersDisplay;
在功能组件的情况下,您声明一个常量,在其中包含一个函数。单击按钮时要调用的内容。但请确保在函数中使用this
。在这种情况下,this
将引用全局执行上下文,并且在该特定上下文中,JavaScript引擎将无法找到属性onAnswer
,因此它将返回undefined
。
只是为了完成这项工作,你已经没有this
传递回调。
像那样:
onClick={onAnswer}
整体而言,代码如下所示:
import React from 'react';
const AnswersDisplay = (props) => {
// even with bind I still get "_this is undefined"
//this.onAnswer = this.onAnswer.bind(this);
const answerList = props.answerList.map( (option) => {
return (
<button
onClick={onAnswer}
value={option}
className="ui basic green button">{option}
</button>
)
});
const onAnswer = (e) =>{
console.log(e.target.value);
}
return(
<div className="ui two buttons hSpace">{this.answerList}</div>
);
};
这个MDN web doc涵盖了你需要了解的关于this
的一切。
为了简单起见,请考虑objects
,其中this
是“未定义的”,除非:
object
(见下面的注释)绑定到bind(this)
,或者通过用object
本身重新绑定外部函数来回弹object
:bind(obj)
。注意:如下所示(在方法6中),有一个例外,在arrow functions
中使用ES5 object
意味着它将保留封闭的词法范围this
而不需要绑定。
例如:
this.prop = "global prop"
const outsideArrowFunction = () => (this.prop)
function outsideFunction() {
return this.prop;
};
const obj = {
prop: "obj's prop",
method: function() {
return this.prop; // returns "obj's prop"
},
method2: function() {
return this; // returns the entire "obj" and its properties
},
method3: function() {
return this.method(); // returns "obj's prop"
},
method4: function() {
return outsideFunction(); // returns "global prop" because the outsideFunction's lexical scope doesn't recognize the "obj"'s nor its properties
},
method5: function() {
return outsideArrowFunction(); // same as method4, utilizes global this
},
method6: function() {
const x = () => this.method();
return x(); // returns "obj's prop" because arrow functions take on "this" from the "obj"
},
method7: function() {
const x = function() {
return this.prop;
};
return x(); // returns "global prop" because "this" loses lexical scope upon execution
},
method8: function() {
const x = this.method.bind(this);
return x(); // returns "obj's prop" because "this" refers to the "obj" upon execution
},
method9: function(callback) {
return callback(this.method);
},
method10: function() {
return this.method9(function(callback) {
return callback(); // returns "global prop" because "this" loses lexical scope upon execution
});
}
};
const a = outsideArrowFunction.bind(obj); // returns "global prop" because arrow functions take on whatever "this" is upon its creation, so "this" refers to the global "this"
const b = outsideFunction.bind(obj); // returns "obj's prop" since a traditional function can rebind "this", which has been rebound to "obj"
console.log(`Method: ${obj.method()}`);
console.log(`Method2: ${obj.method2()}`);
console.log(`Method3: ${obj.method3()}`);
console.log(`Method4: ${obj.method4()}`);
console.log(`Method5: ${obj.method5()}`);
console.log(`Method6: ${obj.method6()}`);
console.log(`Method7: ${obj.method7()}`);
console.log(`Method8: ${obj.method8()}`);
console.log(`Method10: ${obj.method10()}`);
console.log(`arrowFunction: ${a()}`);
console.log(`outsideFunction: ${b()}`);
当谈到classes
时,他们是objects
的模板。所以this
将是undefined
或是一个全球this
除非班级method
已被绑定在constructor
或你使用arrow function
。通过单击每个按钮尝试下面的示例,注意所有3种方法如何工作,但这取决于它们的调用方式:
class Example extends React.Component {
constructor() {
super();
this.state = { method: "" };
this.boundMethod = this.boundMethod.bind(this);
}
componentDidMount() {
this.unboundMethod();
};
boundMethod() {
this.setState({ method: "Bound Method" }); // this works because the method is bound to the class
}
unboundMethod() {
try {
this.setState({ method: "Unbound Method" }); // this only works if it's called within a bound method class (like componentDidMount)
} catch (err) {
alert(err); // however, if it's called within a callback (like in an onClick event), it fails.
}
}
arrowMethod = () => {
this.setState({ method: "Arrow Method" }); // this works because arrow methods are automatically bound to the class
};
render() {
return (
<div>
<button onClick={this.boundMethod}>Bound Method</button>
<button onClick={this.unboundMethod}>Unbound Method</button>
<button onClick={this.arrowMethod}>Arrow Method</button>
<p>The {this.state.method} was called</p>
</div>
);
};
}
ReactDOM.render(<Example />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>