在 React 中对 class 属性使用箭头函数。不清楚

Using Arrow function for class properties in React. Not clear

我发现箭头函数功能在 React 组件中被用作 Class 属性。在线查看我发现它使代码更具可读性,并且由于箭头函数的特性,我们不必在构造函数中绑定 handlEvents 函数。

即使在为 class 属性 使用箭头函数时,我仍然必须使用 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>
   )

}

classes 中早期绑定的箭头函数不受当前 ECMAScript 的正式支持。

使用箭头函数作为 class 方法 will get you in trouble 当您的 class 被继承并且 child 想要覆盖 parent 方法时。

但是,我会说在你的 React 组件中使用它们是非常安全的,因为你不会在这里遇到继承问题,因为使用 React 你通常不会进一步继承你自己的组件(见 Composition vs Inheritance):

At Facebook, we use React in thousands of components, and we haven’t found any use cases where we would recommend creating component inheritance hierarchies.

Dan Abramov 也在组件方法中 using arrow functions,但他建议仅在需要早期绑定时才使用它。

While it’s still experimental, in my experience it solves the problem fairly nicely. It’s not at all React-specific: I find it useful in any classes that deal with asynchrony and callbacks because the binding problem is common for all JavaScript, not just React. We enabled this syntax proposal in the whole Facebook codebase, and if it gets dropped or changes, we’ll make sure to release an automated codemod to migrate to the new syntax (or, worst case, transform it back into bind calls in constructor).

然而,正如 Dan 指出的那样,为了安全起见,请坚持在构造函数中进行早期绑定:

If you want to stick to the language standard, manual binding in constructor is the way to go. It’s tedious but usually you only want to do this for event handlers, and by convention you start them with handle* in React, so it’s not too hard to remember to bind those.


更新: 关于您的案例:

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

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

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

您需要稍微更改一下函数,如下所示。

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>
   )

}

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

绑定高阶函数(或方法)

它只是一个 return 事件回调的方法,因为这是一个已经绑定到此的方法。通过这种方式,您可以将任何参数传递给作为闭包的方法,并且这些参数将出现在回调中。 field 参数就是这种情况。请注意,我切换了参数的顺序,字段应该是第一个,因为它首先被调用到 return 回调。

  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>