나는 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);
});
}
이제 내가해야 할 일은 해당 유틸리티를 가져 와서 생성자에 대한 호출을 추가하는 것이므로 생성자에서 각각의 새로운 메소드를 더 이상 바인딩 할 필요가 없습니다. 새로운 생성자는 이제 다음과 같이 깨끗해 보입니다.
//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);
}
// ...
}
답변
화살표 함수를 사용하고 있으며 생성자에 바인딩합니다. 따라서 화살표 기능을 사용할 때 바인딩을 할 필요가 없습니다.
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);
}
}
또한 렌더링에서 직접 함수를 바인딩하는 것은 권장되지 않습니다. 항상 생성자에 있어야합니다