Как использовать функции стрелок (public class fields) в качестве методов класса?

Я новичок в использовании классов ES6 с React, ранее я привязывал свои методы к текущему объекту (показать в первом примере), но ES6 позволяет мне постоянно привязывать функцию класса к экземпляру класса со стрелками? (Полезно при передаче в качестве функции обратного вызова.) Я получаю ошибки, когда я пытаюсь использовать их, как вы можете, с помощью CoffeeScript:

class SomeClass extends React.Component {

  // Instead of this
  constructor(){
    this.handleInputChange = this.handleInputChange.bind(this)
  }

  // Can I somehow do this? Am i just getting the syntax wrong?
  handleInputChange (val) => {
    console.log('selectionMade: ', val);
  }

Итак, если бы я должен был передать SomeClass.handleInputChange, например, setTimeout, он был бы привязан к экземпляру класса, а не к объекту window.

Ответ 1

Ваш синтаксис слегка выключен, просто отсутствует знак равенства после имени свойства.

class SomeClass extends React.Component {
  handleInputChange = (val) => {
    console.log('selectionMade: ', val);
  }
}

Это экспериментальная функция. Вам нужно будет включить экспериментальные функции в Babel, чтобы получить это для компиляции. Здесь - демонстрация с включенной экспериментальной версией.

Чтобы использовать экспериментальные функции в babel, вы можете установить соответствующий плагин из здесь. Для этой конкретной функции вам нужен плагин transform-class-properties:

{
  "plugins": [
    "transform-class-properties"
  ]
}

Подробнее о предложении для полей классов и статических свойств вы можете прочитать здесь


Ответ 2

Нет, если вы хотите создать связанные, специфичные для экземпляра методы, вам нужно будет сделать это в конструкторе. Однако для этого вы можете использовать функции стрелок, вместо использования .bind по прототипу метода:

class SomeClass extends React.Component {
  constructor() {
    super();
    this.handleInputChange = (val) => {
      console.log('selectionMade: ', val, this);
    };
    …
  }
}

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

В качестве альтернативы вы всегда можете использовать .bind, что позволяет объявить метод на прототипе, а затем привязать его к экземпляру в конструктор. Этот подход имеет большую гибкость, поскольку он позволяет модифицировать метод извне вашего класса.

class SomeClass extends React.Component {
  constructor() {
    super();
    this.handleInputChange = this.handleInputChange.bind(this);
    …
  }
  handleInputChange(val) {
    console.log('selectionMade: ', val, this);
  }
}

Ответ 3

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

Предположим, у меня есть этот класс с конструктором:

//src/components/PetEditor.jsx
import React from 'react';
class PetEditor extends React.Component {
  
   constructor(props){
        super(props);
        this.state = props.currentPet || {tags:[], photoUrls: []};
     
        this.tagInput = null;
        this.htmlNode = null;

        this.removeTag = this.removeTag.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.modifyState = this.modifyState.bind(this);
        this.handleKeyUp = this.handleKeyUp.bind(this);
        this.addTag = this.addTag.bind(this);
        this.removeTag = this.removeTag.bind(this);
        this.savePet = this.savePet.bind(this);
        this.addPhotoInput = this.addPhotoInput.bind(this);
        this.handleSelect = this.handleSelect.bind(this);
        
    }
    // ... actual method declarations omitted
}

Ответ 4

Вопрос готов, но я добавлю несколько примеров использования для использования метода ES6 arrow.

Внутри методов обратного вызова:

let  arr = [1,2];
let arr1 = arr.map((val,index) => {
    return val * 2;
});

или,

let arr1 = arr.map(val => { // if one argument then no need of using ()
    return val * 2;
});

Примечание: внутренняя функция обратного вызова, если используется this, то здесь this ссылка на функцию обратного вызова вместо класса компонента.

Пример:

arr.map(function(val) {
    this.func(val); // Will not work
});

arr.map((val,index)=>{
    this.func(); // Will  work
});

Ответ 5

Вы используете функцию стрелки, а также привязываете ее к конструктору. Поэтому вам не нужно делать привязку при использовании функций стрелок

class SomeClass extends React.Component {
  handleInputChange = (val) => {
    console.log('selectionMade: ', val);
  }
}

ИЛИ вам нужно привязать функцию только в конструкторе, когда вы используете обычную функцию, например, ниже

class SomeClass extends React.Component {
   constructor(props){
      super(props);
      this.handleInputChange = this.handleInputChange.bind(this);
   }

  handleInputChange(val){
    console.log('selectionMade: ', val);
  }
}

Также не рекомендуется привязывать функцию непосредственно к рендерингу. Он всегда должен быть в конструкторе