Programming

화살표 함수 (공개 클래스 필드)를 클래스 메서드로 사용하는 방법은 무엇입니까?

procodes 2020. 5. 27. 22:42
반응형

화살표 함수 (공개 클래스 필드)를 클래스 메서드로 사용하는 방법은 무엇입니까?


나는 React와 함께 ES6 클래스를 처음 사용하고 있는데, 이전에는 메소드를 현재 객체에 바인딩했지만 (첫 번째 예 참조) 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.


구문 이름이 약간 떨어져 속성 이름 뒤에 등호가 없습니다.

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

이것은 실험적인 기능입니다. 이것을 컴파일하려면 Babel의 실험 기능을 활성화해야합니다. 다음 은 실험이 가능한 데모입니다.

babel에서 실험 기능을 사용하려면 여기 에서 관련 플러그인을 설치할 수 있습니다 . 이 특정 기능을 사용하려면 transform-class-properties플러그인 이 필요합니다 .

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

클래스 필드 및 정적 속성 제안에 대한 자세한 내용은 여기를 참조하십시오.



아니요, 바인딩 된 인스턴스 별 메소드를 생성하려면 생성자에서 수행해야합니다. 그러나 .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);
  }
}

이 질문에 대한 답변이 충분하다는 것을 알고 있지만 실험 기능을 사용하지 않으려는 사람들에게는 약간의 기여를합니다. 생성자에서 여러 함수 바인딩을 바인딩하고 지저분한 것처럼 보이게 만드는 문제 때문에 한 번 생성자에서 바인딩되고 호출 된 유틸리티 메소드가 나타났습니다. 필요한 모든 메소드 바인딩이 자동으로 수행됩니다.

생성자와 함께이 클래스가 있다고 가정합니다.

//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
}

지저분 해 보이지 않습니까? 이제이 유틸리티 메소드를 만들었습니다.

//src/utils/index.js
/**
 *  NB: to use this method, you need to bind it to the object instance calling it
 */
export function bindMethodsToSelf(objClass, otherMethodsToIgnore=[]){
    const self = this;
    Object.getOwnPropertyNames(objClass.prototype)
        .forEach(method => {
              //skip constructor, render and any overrides of lifecycle methods
              if(method.startsWith('component') 
                 || method==='constructor' 
                 || method==='render') return;
              //any other methods you don't want bound to self
              if(otherMethodsToIgnore.indexOf(method)>-1) return;
              //bind all other methods to class instance
              self[method] = self[method].bind(self);
         });
}

All I now need to do is import that utility, and add a call to my constructor, and I don't need to bind each new method in the constructor anymore. New constructor now looks clean, like this:

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


You are using arrow function and also binding it in constructor. So you no need to do binding when you use arrow functions

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

OR you need to bind a function only in constructor when you use normal function like below

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

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

Also binding a function directly in render is not recommended. It should always be in constructor

참고URL : https://stackoverflow.com/questions/31362292/how-to-use-arrow-functions-public-class-fields-as-class-methods

반응형