Decorator

 · 1 min read

Decorator is the new feature of ES7! Well, it isn’t really a standard feature now. It’s in Stage 2, but, thanks to babel, we can use it immidiately.

Let’s see a very simple example:

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true

Its purpose seems like what the Decorator Pattern does, right?

A decorator is the name used for a software design pattern. Decorators dynamically alter the functionality of a function, method, or class without having to directly use subclasses or change the source code of the function being decorated.

Decorator signature:

function(target, property, descriptor){}

decorating method of class

class Person {
  @readonly
  name() { return `${this.first} ${this.last}` }
}

But we can not decorate function like this!

var counter = 0;

var add = function () {
  counter++;
};

@add
function foo() {
}

because of function evaluation, the code above is working like this below

@add
function foo() {
}

var counter;
var add;

counter = 0;

add = function () {
  counter++;
};

So we need to wrap the function in order to decorate.

const wrapper = add(foo);

OK, after looking at these features, I bet it would remind you of HOC in React.

React & Redux

class MyReactComponent extends React.Component {}

export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

With decorator, we can write like this:

@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {}

some recommended decorator libraries:

react-decoration: A collection of @decorators for React Components

recompose: Recompose is a React utility belt for function components and higher-order components. Think of it like lodash for React.