bestsource

React.js ES6는 모든 메서드에 '이것'을 바인딩하지 않습니다.

bestsource 2023. 2. 17. 21:30
반응형

React.js ES6는 모든 메서드에 '이것'을 바인딩하지 않습니다.

최근에 React.js를 만지기 시작했는데 너무 좋아요.처음에는 일반 ES5에서 시작했는데, 요령을 알기 위해 모든 문서는 ES5로 되어 있습니다.

하지만 지금은 ES6를 시험해 보고 싶었습니다.그것은 반짝반짝하고 새롭기 때문입니다.또, 몇개의 심플한 기능도 있는 것 같습니다.매우 신경이 쓰이는 것은 컴포넌트 클래스에 추가한 모든 메서드에 대해 이제 '이것'을 바인딩해야 하며, 그렇지 않으면 작동하지 않는다는 것입니다.제 컨스트럭터는 이렇게 됩니다.

constructor(props) {
  super(props);
  this.state = { ...some initial state... }

  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
}

만약 내가 수업에 더 많은 방법을 추가한다면, 이것은 더 크고 추악한 혼란이 될 것이다.

제 질문은 이 문제를 해결하거나 최소한 더 쉽게, 짧게, 덜 추하게 만들 수 있는 방법이 없을까요?Respect with ES6를 시도하고 싶었던 주된 이유 중 하나는 코드를 좀 더 간결하게 하기 위해서였는데, 이것은 그 반대입니다.어떤 제안이나 의견이라도 주시면 감사하겠습니다.

클래스 필드를 사용하여 생성자 외부에서 바인딩을 수행할 수 있습니다.다음과 같이 표시됩니다.

class Foo extends React.Component {

  handleBar = () => {
    console.log('neat');
  };

  handleFoo = () => {
    console.log('cool');
  };

  render() {
    return (
      <div
        onClick={this.handleBar}
        onMouseOver={this.handleFoo}
      />
    );
  }

}

클래스 필드는 클래스 속성 변환을 통해 Babel에 의해 실험적으로 지원되지만, 스테이지 3 드래프트이기 때문에(아직 Babel 사전 설정이 아님) 여전히 "실험적"입니다.

단, ES7까지 또는 Babel에서 기능을 활성화할 때까지 바인딩을 수동으로 수행해야 합니다. 토픽은 Babel의 Respect on ES6+ 블로그 투고에서 간단히 다루어집니다.

또 다른 대안은 데코레이터를 사용하는 것이다.프로토타입에서 getter를 선언하면 인스턴스의 첫 번째 액세스 시 해당 함수의 바인딩된 버전으로 자체 속성을 정의합니다.

하지만 함정이 있어요!개발 과정에서 자산을 대체하는 것이 아니라 모든 접근에 구속될 것입니다., 리액트 핫 로더를 파손하지 않습니다.적어도 나한테는, 그건 꽤 중요한 일이야.

이걸 제공하는 클래스 바인드(class-bind) 라이브러리를 만들었습니다.

import {bound} from 'class-bind';

class App {
  constructor(){
    this.foo = 'bar';
  }

  @bound
  returnsFoo(){
    return this.foo;
  }

  render(){
    var returnsFoo = this.returnsFoo;
    return (
      <div>
        {returnsFoo()} === 'bar'
      </div>
    );
  }
}

데코레이터가 너무 불안정해요?모든 것 또는 어떤 것을 동일한 혜택으로 묶을 수 있습니다.

import {bind, bindAll} from 'class-bind';

bind(App.prototype, 'returnsFoo');

// or
bindAll(App.prototype);

모든 바인드를 정리하는 방법을 만들었습니다.

class MyClass {
  constructor() {

    this.bindMethods([
      'updateLocationFields',
      'render',
      'loadCities',
    ]);
  }

  bindMethods(methods) {
    methods.forEach((item) => {
      this[item] = this[item].bind(this);
    });
  }

  ...
}

Sorallen의 제안은 훌륭하지만 다른 방법을 원한다면 다음과 같습니다.

    class AppCtrlRender extends Component {
        binder(...methods) { methods.forEach( (method) => this[method] = this[method].bind(this) ); }

        render() {
            var isMobile = this.state.appData.isMobile;
            var messages = this.state.appData.messages;
            return (
                <div id='AppCtrlSty' style={AppCtrlSty}>
                    React 1.3 Slider
                    <br/><br/>
                    <div className='FlexBoxWrap'>
                        <Slider isMobile={isMobile}/>
                        <JList data={messages}/>
                    </div>
                </div>
            );
        }
    }

    var getAppState = function() {
        return {
            appData: AppStore.getAppData()
        };
    };

    export default class AppCtrl extends AppCtrlRender {
        constructor() {
            super();
            this.state = getAppState();
            this.binder('appStoreDidChange');
        }

        componentDidMount() {
            var navPlatform = window.navigator.platform;
            Actions.setWindowDefaults(navPlatform);
        }
        componentWillMount() { AppStore.onAny(this.appStoreDidChange); }
        componentWillUnmount() { AppStore.offAny(this.appStoreDidChange); }
        appStoreDidChange() { this.setState(getAppState()); }
    }

이.binder에는 임의의 수의 메서드를 추가할 수 있습니다('method1', 'method2', ...).

「 」를 사용하고 stage-0이치노

class MyComp extends Component {

  handleClick() { console.log('doing things') }

  render() {
    return <button onClick={::this.handleClick}>Do Things</button>
  }

}

경우, 「 」가 파괴됩니다.this.handleClick.call(this)일반적으로 충분한 성능을 발휘한다고 생각합니다.

구속을 피하기 위한 하나의 아이디어

class MyComp extends Component {

  render() {
    return <button onClick={e => this.handleClick(e)}>Do Things</button>
  }

}

면책사항: 검증되지 않은 경우에도 여러 인수를 쉽게 처리할 수 없습니다(이 경우 이벤트(event)가 하나 있습니다).

또, 이 기사에 의하면, 이 답변은 아마도 하지 말아야 할 것의 예라고 할 수 있습니다.이것은 아마 읽을 가치가 있을 것입니다.

https://daveceddia.com/avoid-bind-when-passing-props/

저는 사실 OOP 상속을 모방하여 자녀에게 부모 컨텍스트를 물려주는 것을 선호합니다.

class Parent extends Component {
  state = {happy: false}

  changeState(happy) {
    this.setState({happy})
  }

  render() {
    return (
      <Child parent={this} >
    )
  }
}

class Child extends Component {
   //...
   this.props.parent.changeState(true)
}

0.02달러, 존

각 컨스트럭터에서 호출하는 도우미 함수를 사용합니다.이 예에서는 바인드 됩니다._handleChange1() ★★★★★★★★★★★★★★★★★」_handleChange2().

class NameForm extends React.Component {
    constructor(props) {
        super(props);
        doBinding(this);
        this.state = {value1: "", value2: ""};
    }
    _handleChange1(event) {
        this.setState({value1: event.target.value});
    }
    _handleChange2(event) {
        this.setState({value2: event.target.value});
    }
    render() {
       ...
    }
}

이 방법은 Babel을 사용하지 않아도 작동합니다.

의 핸들러 「」로 한다._(일부러) ★★★★★★★★★★★★★★★★★.doBinding() '찾아보세요'를 ._뺄 수 요.if (key.startsWith("_"))이 관습을 사용하지 않으면요.

function doBinding(obj) {
    const proto = Object.getPrototypeOf(obj);
    for (const key of Object.getOwnPropertyNames(proto)) {
        if (key.startsWith("_")) {
            obj[key] = obj[key].bind(obj);
        }
    }
}

공통 함수를 사용하여 다음과 같이 바인딩 작업을 수행합니다.

// common function:
function bind(self,methods){
     for(var key in methods){
       self[key] = methods[key].bind(self);
     }
}

// your class:
class MyClass {
     constructor() {
          bind(this,{
              someHandler1(event){ 
                //... 
              },
              someHandler2(event){ 
                //...
              }
          })
     }
}

언급URL : https://stackoverflow.com/questions/32192682/react-js-es6-avoid-binding-this-to-every-method

반응형