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?
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);
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