我遇到了箭头函数功能,在React组件中用作Class属性。在线查看时,我发现它使代码更具可读性,并且由于具有箭头功能,我们不必在构造函数内部绑定handlEvents函数。
即使将箭头函数用于类属性,我仍然必须使用bind方法,如下面的代码所示。当我在构造函数中删除绑定时,它在控制台Warning: A component is changing an uncontrolled input of type text to be controlled.
中显示错误,并且表单错误也没有显示出来
class Contact extends Component {
constructor(props) {
super(props);
this.handleBlur = this.handleBlur(this);
}
handleBlur = evt => field => {
this.setState({
touched: { ...this.state.touched, [field]: true }
});
render() {
return(
<Form onSubmit={this.handleSubmit}>
<FormGroup row>
<Label htmlFor="firstname" md={2}>
First Name
</Label>
<Col md={10}>
<Input
type="text"
id="firstname"
name="firstname"
placeholder="First Name"
valid={errors.firstname === ""}
invalid={errors.firstname !== ""}
value={this.state.firstname}
onBlur={event => {
this.handleBlur("firstname");
}}
onChange={this.handleInputChange}
/>
<FormFeedback>{errors.firstname}</FormFeedback>
</Col>
</FormGroup>
</Form>
)
}
答案 0 :(得分:1)
当前ECMAScript不正式支持类中用于早期绑定的箭头功能。
在继承了您的类并且子级想要覆盖父级方法时,将箭头用作类方法will get you in trouble。
但是,我想说在您的react组件中使用它们是非常安全的,因为您不会在这里遇到继承问题,因为使用react时,您通常不会进一步继承自您自己的组件(请参见Composition vs Inheritance ):
在Facebook,我们在成千上万的组件中使用React,但还没有发现建议创建组件继承层次结构的用例。
Dan Abramov在组件方法中也using arrow functions,但是他建议仅在需要早期绑定的情况下才使用它。
虽然仍处于实验阶段,但以我的经验,它可以很好地解决该问题。它根本不是特定于React的:我发现它在处理异步和回调的任何类中都很有用,因为绑定问题不仅对于React,而且对于所有JavaScript都是常见的。我们在整个Facebook代码库中启用了该语法建议,并且如果删除或更改了该语法建议,我们将确保发布自动的codemod以迁移到新语法(或者,在最坏的情况下,将其转换回构造函数中的bind调用)
但是,正如Dan所指出的那样,为了安全起见,请在构造函数中坚持早期绑定:
如果您要遵守语言标准,请在 构造函数是必经之路。这很乏味,但通常您只想要 为事件处理程序执行此操作,按照惯例,您可以使用 在React中处理*,因此记住它们并不太难。
更新:关于您的情况:
在您的情况下,您可以使用Anshul Bansal提供的解决方案,将字段名传递到handleBlur
中,并在将返回的函数作为事件回调传递时在闭包中使用field变量。
或者您可以通过evt.target
(未测试代码)直接访问字段的输入名称。
handleBlur = evt => {
const field = evt.target.name;
this.setState({
touched: { ...this.state.touched, [field]: true }
});
答案 1 :(得分:1)
您需要对功能进行一些如下更改。
class Contact extends Component {
constructor(props) {
super(props);
this.handleBlur = this.handleBlur(this);
}
handleBlur = field => () => {
this.setState({
touched: { ...this.state.touched, [field]: true }
});
render() {
return(
<Form onSubmit={this.handleSubmit}>
<FormGroup row>
<Label htmlFor="firstname" md={2}>
First Name
</Label>
<Col md={10}>
<Input
type="text"
id="firstname"
name="firstname"
placeholder="First Name"
valid={errors.firstname === ""}
invalid={errors.firstname !== ""}
value={this.state.firstname}
onBlur={this.handleBlur("firstname")}
onChange={this.handleInputChange}
/>
<FormFeedback>{errors.firstname}</FormFeedback>
</Col>
</FormGroup>
</Form>
)
}
答案 2 :(得分:0)
我不会使用箭头功能来做到这一点,但是可以。我将解释这两种方法(还有更多方法),第一种是我通常使用的方法。
使用高级函数(或方法)进行绑定
这只是一个返回事件回调的方法,因为该方法已经绑定到此方法。这样,您可以将任何参数传递给作为闭包的方法,并且这些参数将出现在回调中。 field
参数就是这种情况。请注意,我切换了参数的顺序,字段应该是第一个,因为它首先被调用来返回回调。
handleBlur(field) {
return evt => {
console.log(this.state);
this.setState({
touched: { ...this.state.touched,
[field]: true
}
});
};
}
您可以将其简单地绑定为:
onBlur = {this.handleBlur("firstname")}
它的优点是您不需要在构造函数中绑定到此。
使用箭头功能
代码相似,但是您必须在构造函数中绑定此代码。
handleBlurArrow = field => evt => {
console.log(this.state);
this.setState({
touched: { ...this.state.touched,
[field]: true
}
});
};
绑定:
onBlur = {this.handleBlurArrow("firstnameArrow")}
在构造函数上绑定此
: this.handleBlurArrow = this.handleBlurArrow.bind(this);
工作示例
class Contact extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.handleBlurArrow = this.handleBlurArrow.bind(this);
}
handleBlurArrow = field => evt => {
console.log(this.state);
this.setState({
touched: { ...this.state.touched,
[field]: true
}
});
};
handleBlur(field) {
return evt => {
console.log(this.state);
this.setState({
touched: { ...this.state.touched,
[field]: true
}
});
};
}
render() {
return (<div>
<input type = "text" id = "firstname"
name = "firstname"
placeholder = "First Name"
value = {this.state.firstname}
onBlur = {this.handleBlur("firstname")}
onChange = {this.handleInputChange}
/>
<input type = "text" id = "firstnameArrow"
name = "firstname"
placeholder = "First Name Arrow"
value = {this.state.firstname}
onBlur = {this.handleBlurArrow("firstnameArrow")}
onChange = {this.handleInputChange}
/>
</div>
)
}
}
ReactDOM.render( <Contact /> ,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>