Reputation: 953
How to bind this
with transform-decorators-legacy
Babel plugin?
For example I have some simple decorator. Decorator works, but this
is undefined on component's method.
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)
}
}
If I try to use @myDecorator with some @autobind decorators I get
TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
, because
A data descriptor is a property that has a value, which may or may not be writable. An accessor descriptor is a property described by a getter-setter pair of functions. A descriptor must be one of these two flavors; it cannot be both.
In my example I can not use value()
and get()
.
Binding in the constructor (this.myMethod = thid.myMethod.bind(this)
) doesn't seem to be helpful either, because you bind undecorated method.
Upvotes: 1
Views: 4606
Reputation: 15642
Is it not the problem with .bind
ing decorated methods.
But there is something that you missed. Even though you did .bind
your myMethod
inside your constructor
to the class, when you invoke it, no matter from where, myDecorator
modifies the execution scope.
oldValue.apply(null, arguments)
Basically, you replaced target scope (MyClass
) with null
.
So what you want is this:
oldValue.apply(this, arguments)
See this fiddle: http://jsfiddle.net/free_soul/0n6v1dtp/
Upvotes: 2
Reputation: 953
This is how I managed to solve this: Using code from mentioned @autobind decorator:
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)
};
}
};
}
Upvotes: 2