How do decorators in es6 work?

2019-06-03 06:12发布

I'm learning redux and see that the examples in the doc use connect in this signature:

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

But in other places from other repos I've also seen this-

@connect(mapStateToProps, mapDispatchToProps)

I get that there the same thing but how does the signature of a decorator work? It doesn't look like it's setting a variable to the result of the connect so where does the function of @connect go to and get assigned to?

2条回答
姐就是有狂的资本
2楼-- · 2019-06-03 06:46

Decorators are just higher-order functions that work on the next thing that they see.

This is sort of cheating (not really sort of, it is), but if we simplified this to a format that you could reason about using just simple values:

const add = x => y => x + y;

Add is a function that expects an x, and returns a function that expects a y,
and then returns x + y;
You can call it like

add(1)(2); // 3

or

const add1 = add(1);
add1(2); // 3

But what if we had some way of telling JS not to expect to pass in the last value, but instead just run what it has on the next thing it sees.

@add(1)
2; // 3

@add1
2; // 3

Like I said, this example doesn't really work this way (in that a decorator function wouldn't really be meant for adding two numbers, so much as modifying classes or methods or parameters), but that is the basic concept behind the decorators.

@connect(mapProps, mapHandlers)
MyComponent;

is the same as saying

connect(mapProps, mapHandlers)(MyComponent);
查看更多
我想做一个坏孩纸
3楼-- · 2019-06-03 06:49

If you dont understand it in theory then maybe a visual will help. Lets say you are using redux-form and connect and react-autofill for a form on your page. you could use decorators to use it like so.

@connect(mapStateToProps, mapDispatchToProps)
@autofill
@reduxForm({form: 'somethingForm', enableReinitialize: true})
class Something extends React.Component {
    ....
} 

The equivalent of this without decorators would be

class Something extends React.Component {
    ....
}
Something = reduxForm({
    form: 'somethingForm',
    enableReinitialize: true
})(Something);
Something = connect(mapStateToProps, mapDispatchToProps)(autofill(Something));

so think of it like this. top to bottom is last to first order in terms of application for each function. you apply reduxForm, then autofill, then connect in both cases. the decorators just make it simpler to write and less messy code as well

查看更多
登录 后发表回答