Skip to content

Instantly share code, notes, and snippets.

@jkantr
Last active February 16, 2018 15:42
Show Gist options
  • Save jkantr/8fa4f3412626f10a4c93a15bf4bcf9ee to your computer and use it in GitHub Desktop.
Save jkantr/8fa4f3412626f10a4c93a15bf4bcf9ee to your computer and use it in GitHub Desktop.
Why (and why not) decorators
/** when wrapping a function with many other functions, the identity of the
original function quickly gets lost, and it's hard to make sense of it
at a glance */
const Timer = inject("someStore")(observer(class Timer extends React.Component {
/* ... */
}))
/** you can make it less hard to read by separating your component's definition
and it's functional wrappers **/
class Timer extends React.Component {
/* ... */
}
// somewhere much farther down the file...
export default inject('someStore')(observer(Timer))
/** so.. now you don't know what your function is doing at the point of it's definition
this is a Generally Bad Thing **/
/** one solution is decorators, which declare the wrapped functionality right
along with your function / component / class */
@inject('someStore') @observer
class Timer extends React.Component {
}
/** so this is nice... except now you're using experimental syntax (which has already broken,
see babel-plugin-transform-legacy-decorators), this is also a Generally Bad Thing...
so what is another solution?
just declare the wrapper along with the component, where you would otherwise decorate it*/
const wrap = compose(inject('someStore'), observer);
class Timer extends React.Component {
/* ... */
}
export default wrap(Timer);
/** sure, there's nothing explicitly tying together the wrapper and the component, but
the understanding that the component *will* be wrapped with the composed wrapping fn
makes it just as easy to understand (if not easier) than needing to use decorator syntax */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment