Реакция привязки через конструктор - можно автоматизировать? - PullRequest
0 голосов
/ 29 октября 2018

Согласно рекомендациям других, я связывал методы класса в конструкторе React, например:

constructor(props) {
  super(props);
  this.handleChange = this.handleChange.bind(this);
}

У меня есть компоненты со многими методами, и я связываю все эти методы с this . Ах, какая боль! Чтобы избежать повторного поддержания этого шаблона, я построил функцию, которая будет вызываться в конструкторе вместо всех отдельных вызовов; он связывает все методы, специфичные для этого класса, в то время как родительский класс будет заботиться о своих собственных методах, перемещающихся вверх по классам. Например:

function bindClassMethodsToThis(classPrototype, obj) {
    Object.getOwnPropertyNames(classPrototype).forEach(prop => {
        if (obj[prop] instanceof Function && prop !== 'constructor') {
            obj[prop] = obj[prop].bind(obj);
            console.log(`${classPrototype.constructor.name} class binding ${prop} to object`);
        }
    });
}

class A {
    constructor() {
        bindClassMethodsToThis(A.prototype, this);
    }

    cat() {
        console.log('cat method');
    }
}

class B extends A {
    constructor() {
        super();
        bindClassMethodsToThis(B.prototype, this);
    }

    dog() {
        console.log('dog method');
    }
}

let b = new B();

Итак, React и ES6, это разумный подход, или я здесь что-то не так делаю? Должен ли я придерживаться отдельных привязок к это ?

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Ваша стратегия кажется разумной, хотя есть некоторые крайние случаи, которые вы можете решить. Библиотека типа react-autobind, о которой Александр упомянул , позаботится о некоторых из этих вещей для вас, и если бы я использовал эту стратегию, я бы, вероятно, использовал бы такую ​​библиотеку, как эта (или загляните в исходный код, чтобы понять, что он делает).

Для полноты, некоторые альтернативные подходы:

  1. Используйте свойства класса и функции стрелок (вместе со всеми необходимыми преобразованиями Бабеля) для создания предварительно связанных методов:

    class MyComponent extends React.Component {
      handleChange = () => { /* ... */ }
    }
    
  2. Используйте декоратор, такой как autobind декоратор из core-decorators , вместе со всеми необходимыми преобразованиями Бабеля (эту стратегию я использовал ранее):

    import { autobind } from 'core-decorators'
    
    class MyComponent extends React.Component {
      @autobind
      handleChange() { /* ... */ }
    }
    
  3. Изучите использование Hooks (в настоящее время в альфа-режиме), чтобы избежать проблемы связывания всех вместе (поскольку значения состояния и установщики существуют как локальные переменные, которые должны быть закрыты). Эту стратегию я предпочел совсем недавно, но учтите, что она все еще находится в состоянии заявки и может измениться. :)

0 голосов
/ 29 октября 2018

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

class Foo extends React.Component {
  handleClick = (event) => {
    event.preventDefault()
  }

  render() {
    return <div onClick={this.handleClick}>Click me</div>
  }
}
...