Skip to content

Easily Add an Babel Plugin #411

Closed
Closed
@birdwell

Description

@birdwell

Note from maintainers

For people coming to this thread later—if you use MobX or a similar library, you don’t need decorators. They are just syntax sugar in this case.
Learn more: #214 (comment), #411 (comment).
Here is why we don’t include them: #411 (comment).

The setup is excellent. I need to add the babel plugin ""transform-decorators-legacy"" because a library I'm using has decorators. Yet, I do not want to eject for one simple babel plugin. Is there a way to add a babel plugin without ejecting?

Activity

eliperelman

eliperelman commented on Aug 9, 2016

@eliperelman
Contributor

@birdwell No, and that is by design. If you need to deviate from the standard babel configuration, you will need to eject. Thanks!

gaearon

gaearon commented on Aug 9, 2016

@gaearon
Contributor

need to add the babel plugin ""transform-decorators-legacy"" because a library I'm using has decorators.

This sounds a but confused. If a library uses decorators internally, presumably it is transpiled to ES5 on build so this shouldn’t be an issue.

If a library tells you to use decorators, most likely there is an alternative way of using it without them. For example people commonly say MobX “needs” decorators but it couldn’t be further from truth: you can use plain functions instead.

gaearon

gaearon commented on Aug 9, 2016

@gaearon
Contributor

If you can clarify which library you meant, I can point you to an example of using it without the decorator syntax.

birdwell

birdwell commented on Aug 10, 2016

@birdwell
Author

Hey Dan, this the library. Thanks a ton. Great work to all of you guys on this project. You are right there is probably an easy way to get around using them. @gaearon

lacker

lacker commented on Aug 10, 2016

@lacker
Contributor

Basically putting a decorator @foo before the definition of X is the same as saying X = foo(X) after X is defined. It's like one more line of code to do things without decorators.

So there's two decorators in that react-redux-firebase example. One is connect in react-redux. http://redux.js.org/docs/basics/UsageWithReact.html has some examples of using it with no decorator.

To convert the firebase decorator, look at one of their examples like https://github.com/tiberiuc/redux-react-firebase/blob/master/example/App.js -

@firebase()
class TodoItem extends Component {
  // Lots of stuff here
}

Instead of that you could just do

class TodoItem extends Component {
  // Lots of stuff here
}
TodoItem = firebase()(TodoItem)

Hopefully that helps!

alexanderchr

alexanderchr commented on Aug 10, 2016

@alexanderchr

Adding to what @lacker says, I believe that applying HOCs as functions instead of decorators should not be a way to do it, but the preferred way, for three reasons:

  1. It's standardised and one less dependency
  2. It uses the same syntax for functional and class components
  3. It allows exporting the unwrapped component for testing

Where point three is the most important one because when testing you usually want to test your component, not the HOC.

// Todo.js

export class Todo extends Component {
  // ...
}

// Defining an enhance function is down to personal preference, but I find using it in
// combination with a compose function to be a lot cleaner when using multiple HOCs
const enhance = compose( // compose can be imported from redux or recompose
  firebase(),
  /* more HOCs */
);

export default enhance(Todo);
// Todo.test.js

import EnhancedTodo, { Todo } from 'Todo.js';

// EnhancedTodo is the component wrapped by any HOCs
// Todo is the bare component
gaearon

gaearon commented on Aug 10, 2016

@gaearon
Contributor

Another nice thing that’s nice to know: you can chain decorators applied as functions with any functional composition helper. Redux provides compose, you can find the same function in Lodash as flowRight:

import { compose } from 'redux'

class MyThing extends Component {
  // ...
}

// compose multiple "decorators"
const enhance = compose(
  connect(mapStateToProps),
  injectLocale(),
  firebase()
)

// export wrapped component
export default enhance(MyThing)
birdwell

birdwell commented on Aug 11, 2016

@birdwell
Author

@gaearon @alexanderchr @lacker Thank you guys so much! Learned a bunch from those three comments. Plus, now I don't have to eject. 😄 👍

Update: Got my project working with above methods and no ejecting! Thank you again!

seanrasmussen

seanrasmussen commented on Aug 26, 2016

@seanrasmussen

As create-react-app is probably more for people starting out, my vote would be to add the decorators to the basic kit. Makes it easy to follow existing tutorials, without having to insert a different syntax and to get it working. For example this great tutorial on MobX us strewn with decorators. https://www.youtube.com/watch?v=nYvNqKrl69s. I'm having to go through and alter code and for a newbie it just makes getting it working a bit more painful...

BTW- Thanks for all you guys do. I LOVE create-react-app.

gaearon

gaearon commented on Aug 26, 2016

@gaearon
Contributor

Our position is simple: we add transforms that are either stable enough (like async/await) or heavily used by Facebook (like class properties). Only that lets us be confident in suggesting them, because if something changes in the standard, we’ll write and release a codemod to migrate away from them.

Since we don’t currently use decorators, we don’t take it upon ourselves to provide a migration path if the standard becomes incompatible. Additionally decorators aren’t even officially supported by Babel (-legacy is there for a reason). And when they are configured slightly incorrectly people blame React.

So no, we won’t provide support for them until they either become a part of the language, or we start using them internally at Facebook. Sorry! Bring it up with the tutorial authors because MobX absolutely does not require decorators.

jkrems

jkrems commented on Aug 26, 2016

@jkrems

Another argument against adding the -legacy transform is that any decorator written against it is - as it stands - incompatible with the current decorators proposal. There's multiple breaking changes between the stage-0 proposal (implemented by the -legacy transform) and the current stage-2 proposal. So if you use one of the -legacy-style decorators in your code, you run the risk of locking yourself out of future versions of babel or at least making the upgrade a lot more painful.

seanrasmussen

seanrasmussen commented on Aug 26, 2016

@seanrasmussen

Thanks Dan,

The frontend JS ecosystem has many permutations and it really slows down learning and gettingstuffdone for JSnewbies like me. The reason I like React/Redux so much is that the community is so active and supportive. Cheers!

arisAlexis

arisAlexis commented on Aug 26, 2016

@arisAlexis

Decorators would be a very nice addition to have and frankly do you really think they will not be included in JS in the future? Angular uses them heavily, Typescript uses them, Mobx uses them.

gaearon

gaearon commented on Aug 26, 2016

@gaearon
Contributor

@arisAlexis I’m afraid you missed my comment where I described exactly why we don’t include them in this tool. Whether I think they will become a part of JS or not is irrelevant here.

17 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @lacker@eliperelman@jkrems@gaearon@arisAlexis

        Issue actions

          Easily Add an Babel Plugin · Issue #411 · facebook/create-react-app