Использование функции Arrow для свойств класса в React.Не ясно - PullRequest
0 голосов
/ 15 ноября 2018

Я наткнулся на функцию стрелки, которая используется как свойство класса в компоненте React. Посмотрев в Интернете, я обнаружил, что он делает код более читабельным, и из-за особенностей функции стрелки нам не нужно связывать функцию handlEvents внутри конструктора.

Мне все еще нужно использовать метод связывания даже при использовании функции стрелки для свойства класса, как показано в коде ниже. Когда я удаляю привязку в конструкторе, она показывает ошибку в консоли 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>
   )

}

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Вам нужно немного изменить функцию следующим образом.

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 голосов
/ 15 ноября 2018

Я бы не стал делать это с помощью стрелки, но вы можете. Я объясню два метода (есть еще несколько), первый - тот, который я обычно использую.

Связывание с функцией (или методом) более высокого порядка

Это просто метод, который возвращает обратный вызов события, так как этот метод уже связан с этим. Таким образом, вы можете передать любые аргументы методу, который является замыканием, и эти аргументы будут присутствовать в обратном вызове. Это случай аргумента 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>
0 голосов
/ 15 ноября 2018

Функции стрелок для ранних привязок в классах официально не поддерживаются текущим ECMAScript.

Использование функций стрелок в качестве методов класса доставит вам неприятности , когда ваш класс наследуется, и ребенок хочет переопределить родительский метод.

Тем не менее, я бы сказал, что использовать их в ваших компонентах реагирования довольно безопасно, поскольку у вас не возникнет проблем с наследованием, поскольку с помощью реакции вы обычно не будете наследовать от своих собственных компонентов (см. Состав против Наследование ):

В Facebook мы используем React в тысячах компонентов, и мы не нашли случаев использования, в которых мы бы рекомендовали создавать иерархии наследования компонентов.

Дэн Абрамов использует функции стрелок и в компонентных методах, однако он рекомендует использовать его, только если требуется раннее связывание.

Хотя это все еще экспериментально, по моему опыту, это решает проблему довольно хорошо. Это совсем не относится к React: я считаю его полезным в любых классах, которые имеют дело с асинхронностью и обратными вызовами, потому что проблема связывания является общей для всего JavaScript, а не только для React. Мы включили это предложение синтаксиса во всей кодовой базе Facebook, и если оно будет удалено или изменено, мы обязательно выпустим автоматический кодовый мод для перехода на новый синтаксис (или, в худшем случае, преобразуем его обратно в вызовы связывания в конструкторе) .

Однако, как отмечает Дэн, чтобы быть на безопасном сайте, придерживайтесь раннего связывания в конструкторах:

Если вы хотите придерживаться языкового стандарта, ручное связывание в Конструктор это путь. Это утомительно, но обычно вы хотите только сделать это для обработчиков событий, и по соглашению вы начинаете их с обрабатывать * в React, так что не сложно запомнить их.


Обновление: относительно вашего дела:

В вашем случае вы можете использовать решение, предоставленное Anshul Bansal, в котором вы передаете имя поля в handleBlur и используете переменную поля в вашем закрытии, когда вы передаете возвращенную функцию в качестве обратного вызова события.

Или вы можете напрямую получить доступ к имени ввода поля через evt.target (код не проверен).

handleBlur = evt => {
    const field = evt.target.name;
    this.setState({
    touched: { ...this.state.touched, [field]: true }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...