Свяжите это при использовании декораторов методов в React

Как связать this с transform-decorators-legacy плагином Babel? Например, у меня есть простой декоратор. Декоратор работает, но this не определен в методе компонента.

fucntion myDecorator(target, name, descriptor) {
    var oldValue = descriptor.value;

    descriptor.value = function() {
        ...// Doing some stuff here I need the decorator for
        ...// (for example logging on every method call)
        return oldValue.apply(null, arguments);
    };

    return descriptor;

}

class MyClass extends React.Component {
    @myDecorator
    myMethod() {
        ...// this.props... is unavailable here(`this` is undefined)
    }
}

Если я попытаюсь использовать @myDecorator с некоторыми @autobind декораторов я получаю TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, потому что

Дескриптор данных - это свойство, имеющее значение, которое может быть, а может и не быть доступным для записи. Дескриптор доступа - это свойство, описываемое парой функций геттер-сеттер. Дескриптор должен быть одной из этих двух разновидностей; не может быть и того, и другого.

В моем примере я не могу использовать value() и get().

Привязка в конструкторе (this.myMethod = thid.myMethod.bind(this)) тоже не кажется полезной, потому что вы привязываете недекорированный метод.


person OlehZiniak    schedule 28.11.2016    source источник


Ответы (2)


Разве это не проблема .binding декорированных методов.

Но есть кое-что, что вы упустили. Несмотря на то, что вы сделали .bind свой myMethod внутри своего constructor классу, когда вы вызываете его, независимо от того, откуда myDecorator изменяет область выполнения.

oldValue.apply(null, arguments)

По сути, вы заменили целевую область (MyClass) на null.

Итак, что вы хотите:

oldValue.apply(this, arguments)

См. Эту скрипку: http://jsfiddle.net/free_soul/0n6v1dtp/

person yadhu    schedule 28.11.2016
comment
Делая то, что вы предложили, this указывает на React.Component, а не на MyClass - person OlehZiniak; 28.11.2016
comment
Хм, вроде работает. Забавно, я на 100% уверен, что пробовал тот же подход, но он не работал, а this был undefined. Не могли бы вы объяснить, зачем вам понадобилась строка props = this.props? - person OlehZiniak; 28.11.2016

Вот как мне удалось это решить: используя код из упомянутого @ декоратор autobind:

function myDecorator(target, key, descriptor) {
    let fn = descriptor.value;

    return {
        configurable: true,

        get() {
            let boundFn = fn.bind(this);
            Reflect.defineProperty(this, key, {
                value: boundFn,
                configurable: true,
                writable: true
            });

            return function() {
                ...// Doing some stuff here I need the decorator for
                ...// (for example logging on every method call)
                return boundFn.apply(this, arguments)
            };
        }
    };
}
person OlehZiniak    schedule 28.11.2016
comment
Я не думаю, что это необходимо, вместо этого вы можете просто сделать это: var oldValue = descriptor.value; descriptor.value = function() { return oldValue.apply(this, arguments); } return descriptor; Проверьте скрипку в моем ответе. - person yadhu; 28.11.2016
comment
Это потому, что ваша первая привязка к this в конструкторе вашего примера. Это не сработает для декораторов, которым требуются параметры. - person Chris Sullivan; 20.06.2017