在React中使用箭头函数作为类属性。不太清楚。

5
我发现箭头函数特性被用作React组件中的类属性。在网上查找后,我发现这使代码更易读,因为箭头函数特性让我们无需在构造函数内绑定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>
   )

}

抱歉误解了你的问题:D 无论如何,还有一种替代已接受答案的方法,请看我的更新。 - Felix K.
3个回答

2

在当前的ECMAScript标准中,箭头函数作为类的早期绑定并不被官方支持。

当你的类被继承且子类想要覆盖一个父类方法时,使用箭头函数作为类方法会让你遇到麻烦

然而,在react组件中使用它们是相当安全的,因为你不会因为继承而遇到麻烦,通常你不会从你自己的组件进一步继承(参见Composition vs Inheritance):

在Facebook公司,我们在成千上万个组件中使用React,并没有发现任何需要创建组件继承层次结构的用例。

Dan Abramov 也在组件方法中使用箭头函数,但他只建议在需要早期绑定时使用它。

虽然它仍然是实验性的,但根据我的经验,它解决了这个问题。它并不是React特定的:我发现它在任何处理异步和回调的类中都很有用,因为绑定问题对所有JavaScript都是常见的,而不仅仅是React。我们在整个Facebook代码库中启用了这个语法提案,如果它被删除或更改,我们将确保发布自动代码转换程序来迁移到新语法(或者最坏的情况下,在构造函数中将其转换回绑定调用)。

但是正如Dan所指出的,为了安全起见,请在构造函数中使用早期绑定:

如果你想遵循语言标准,手动绑定构造函数是正确的做法。虽然这很繁琐,但通常你只需要为事件处理程序这样做,并且按照惯例,在React中你会以handle*开头,所以记住绑定它们并不太难。


更新: 关于您的情况:

在您的情况下,您可以使用 Anshul Bansal 提供的解决方案,将字段名传递给您的 handleBlur,并在将返回的函数作为事件回调时在闭包中使用 field 变量。

或者,您可以直接通过 evt.target 访问字段的输入名称(未经测试的代码)。

handleBlur = evt => {
    const field = evt.target.name;
    this.setState({
    touched: { ...this.state.touched, [field]: true }
});

谢谢伙计,这是一个关于类属性中箭头函数的很好的解释,涵盖了所有方面!但我想知道为什么它在我的组件中没有按照预期工作?! - Haris Khan
啊,让我快速检查一下。 - Felix K.

0
你需要按照以下方式稍微修改一下这个函数。
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>
   )

}

0

我不会使用箭头函数,但你可以。我将解释两种方法(还有几种方法),第一种是我通常使用的方法。

通过高阶函数(或方法)绑定

这只是一种返回事件回调的方法,因为这是一个已经绑定了this的方法。这样,您可以将任何参数传递给闭包方法,并且这些参数将出现在回调中。这是field参数的情况。请注意,我交换了参数的顺序,应先调用field以返回回调。

  handleBlur(field) {
    return evt => {
      console.log(this.state);
      this.setState({
        touched: { ...this.state.touched,
          [field]: true
        }
      });     
    };
  }

你可以简单地绑定它:

onBlur = {this.handleBlur("firstname")}

这样做的好处是您不需要在构造函数中绑定this。

使用箭头函数

代码类似,但您必须在构造函数中绑定this。

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>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接