Hacker News new | past | comments | ask | show | jobs | submit login
React on ES6+ (babeljs.io)
260 points by clessg on July 8, 2015 | hide | past | favorite | 93 comments



This might be a silly question, but was there ever any thought put towards using ES6 Template Strings rather than the JSX syntax additions? For example:

    class OuterComponent extends React.Component {
      render() {
        return (
          <MixinComponent>
            <InnerComponent />
          </MixinComponent>
        );
      }
    }
Being replaced by something more like:

    class OuterComponent extends React.Component {
      render() {
        return JSX`
          <MixinComponent>
            <InnerComponent />
          </MixinComponent>
        `;
      }
    }



Rightio, that sort of explains their rationale. Although this doesn't really help:

    However, this would lead to further divergence. Tooling that is built around the assumptions imposed by template literals wouldn't work. It would undermine the meaning of template literals. It would be necessary to define how JSX behaves within the rest of the ECMAScript grammar within the template literal anyway.
I'm not really what the problem is here. Template strings seem to have been put in ES6 partly to do what JSX does, so it seems very odd that anyone went to the lengths of defining a language extension rather than use them.


As I understand it, the problem is that template strings evaluate to strings, whereas JSX evaluates to function calls creating a data structure. So render would produce a string, React would have to parse it back out of the XML syntax to figure out the structure of the data hidden in the string, and then make function calls. That's expensive.

More importantly, how would you share data structures? `<Todos items=${someObject}>` would return a string with the string representation of someObject, but it wouldn't be the same object, have methods, etc.


You could probably use a tagged template literal that would return an object representation of the given string. Tagged template literals don't have to return strings; jsx`<Todos items=${someObject}>` could return an Element object, for example.


But the input is still a string? I think it's helpful to know that when you see JSX like this:

    <MixinComponent>
      <InnerComponent name='madeofpalk'/>
    </MixinComponent>

JSX will convert that into regular JS which will look like

    element('MixinComponent', {},
        element('InnerComponent', {name: 'madeofpalk'})
    )
Parsing that string during runtime to produce the above data structure isn't ideal.


Right, for sure. Template literals are not a good replacement for JSX.


Tooling and static analysis. ESLint can tell me if `MixinComponent` is undefined during parse time.


Would you be able to use template strings inside the template if this was the case?


Yes, template strings can be nested (well, they can using Babel).


This works for me in the latest Chrome too:

    `${`test`}`


Good point.

Since JSX is just JavaScript, it doesn't have any problems with nesting.


"MixinComponent" and "InnerComponent" are identifiers of regular javascript variables. You would need to wrap them each with ${}. Also, the string would have to be parsed every time render() is called.


I understand the interest in new Javascript standards in the browser however I've been doing a lot of React+CoffeeScript (without JSX) work lately and it can do all of what is mentioned in the article in a more expressive and (imho) more beautiful syntax.

I'm genuinely curious about all the ES6/ES7 articles. Is the interest driven from the eventual native support in future browsers and being able to drop transpiler dependencies?


IMHO the CoffeeScript syntax is ugly and confusing.

ES6 improves the language without borking the syntax so much.

To add something more constructive, CoffeeScript is still just a transpiler. I think the long-term goal is for browsers to "natively" interpret/run ES6 code rather than forever transpiling to ES5. Either that, or we actually move on to something like web assembly.


That's your personal opinion as it's his about ES6


> I think the long-term goal is for browsers to "natively" interpret/run ES6 code rather than forever transpiling to ES5.

That's not an opinion; this will actually happen. See this: https://kangax.github.io/compat-table/es6/


Did you miss the part where I started my entire comment with "IMHO"?


Whats the state on coffeescript+jsx these days? I had a horrible time getting it transpile correctly (with gulp) about a year ago.


We use CJSX at OneRent with Grunt and Browserify and it's been nothing but fantastic. The syntax is terse and beautiful and IT saves us a lot of typing. To me, ES6 just seems like a lot of catch-up to CoffeeScript, while still maintaining much of the unnecessarily verbose syntax of JS.


I stopped using JSX with React+CoffeeScript. I think the following looks a lot cleaner and removes the jsx dependency:

    {div, a} = React.DOM
    ...
    render: ->
      (div {},
        (a {href: 'foo'}, 'bar')
      )
The only downside is having to extract the tags from React.DOM.


You could omit the parenthesis and it starts to look a lot like HAML :-)


The parens help to make sure CoffeeScript parses it correctly. Plus it looks kind of Lispy which is good right?


"looks kind of Lispy which is good right?" :D, you sound not sure :)

I haven't had any issues without the parens, but then again I've only just fooled around.

You probably know better.


Wouldn't you have to use `React.createFactory` in this case as well? (when not dealing with React.DOM components)


Yes you do need to use it. I put each component in its own file and use Browserify to require them in like this:

    MyComponent = React.createFactory require './my-component'
then you can do

    render: ->
      (div {},
        (MyComponent {})
      )


Works very well in typescript as well !


The code is just so clean. I never understand why it's not more widely used. The JSX blocks are just so clean without all of the braces and the like, and even get syntax highlighted as HTML in sublime.


We've had pretty good success compiling cjsx with gulp-cjsx. The one annoyance I've noticed is that it's just a tad more finicky about whitespace and parentheses/brackets than normal coffeescript, but I suppose that's to be expected.


If there is a particular case which you think should work but doesn't, please file an issue on the coffee-react-transform repo and I'll look into it.


Here's a random template I made with react in middleman that uses coffeescript with no jsx if anyones curious, https://github.com/jbhatab/middleman-backbone-react-template. I love the syntax and think it's really clean. The view code reminds me of slime.


For me the nice thing is that we're converging. I like the features added by all of the languages that transpile to js, but I want to be able to use them consistently across every project I'm involved in and being an official part of the language makes that much more likely. Convergence is also a boon for tooling and interop.


Can you give some examples like the ones he gave in the article but in react+coffeescript without jsx?

edit: Someone else posted that https://github.com/jbhatab/middleman-backbone-react-template...

Everytime I see people saying bad things about coffeescript I really wonder why. This looks way nicer/clearer to me.


I tried to use it with LiveScript (without JSX) but it was a horrible mess. All those commas and nulls.

If there were something like CoffeeScript+JSX for LiveScript I would be sold.


Basically JavaScript is a tool that I can leverage in more places then CS and CS offers me very little advantage over ES6.


> I can leverage in more places then CS

Doesn't ES6 still require transpiling for maximum compatibility at this point? I would reverse your statement; aside from polyfills, ES6 offers me very little advantage over CS.


Both CS and ES6 use transpilers. ES6 syntax is ugly and adds no features. ES6 makes me think: the emperor has no clothes.


No features? Destructuring, arrow functions, module system, default values, spread operator, decorators, template strings, on and on. It provides almost all of CoffeeScript's features. What advantage do you see CoffeeScript having?


None of those features are new - I can get everything on your list with CoffeeScript. For me the advantage of CoffeeScript is that it is less verbose. Main advantage that I see in ES6 is that Transpiling is now widely accepted.


What's the status of mixins? How could I do something similar in terms of functionality in ES6?


You have 3 options if you want mixin behaviour:

- Use old syntax or explicitly add mixin to prototype - Use composition. A bit annoying, because you have to make an extra class

    class OuterComponent extends React.Component {
      render() {
        return (
          <MixinComponent>
            <InnerComponent />
          </MixinComponent>
        );
      }
    }

    class InnerComponent extends React.Component{}
- wait for decorators (?)


You can at least try decorators with babel using[1]

  $ babel --optional es7.decorators
or

  babel.transform("code", { optional: ["es7.decorators"] });
Here[2] is an article that describes how to use it for mixins

[1] https://babeljs.io/docs/usage/experimental

[2] http://raganwald.com/2015/06/26/decorators-in-es7.html


Possibly decorators proposed for ES7 would be a solution here? Babel and TypeScript already support them.

By the way, TypeScript recently (in nightly) gained support for JSX, so we can now have all of this ES6 stuff + types on top of it.


I wrote a small utility for using mixins with my React components. I've been finding it really useful. The notes assume you're using ES7 decorators. But you could easily use it with ES5/6 syntax by treating it as a normal function and just passing your class to it.

https://www.npmjs.com/package/mixin-decorator

edit: a link would be helpful, right?


Mixins are being considered for ES2016: https://esdiscuss.org/topic/about-lightweight-traits meanwhile you can Object.assign behavior into things.


I've been working on a ES6 composition-based library that might help out here: https://www.npmjs.com/package/fabricant

The idea is you declare which components will be needed and the library takes care of instantiating objects with the necessary components for you. It works something like Unity (the game engine)'s entity-component architecture.

I haven't tried to get it working with React yet though, I've been playing with threejs instead :)


Not yet supported afaik [1]. I've used react-mixin [2] with some success.

[1] https://facebook.github.io/react/blog/2015/01/27/react-v0.13...

[2] https://github.com/brigand/react-mixin


Looks like a great idea, a nice intermediate step while the decorators are not widely used. I wonder what didn't work out as you said "some success"?


We have a few rather complex mixins in React-Router-Component and react-mixin's decorators worked just fine [1]. The only limitation I see now is a mixin that defines more mixins; this currently doesn't work, but there's no reason why it couldn't. I am considering a patch.

1. https://github.com/STRML/react-router-component/blob/master/...


Thank you for the heads up and the example.

> The only limitation I see now is a mixin that defines more mixins; this currently doesn't work

Why and how would you do this?


It's just a nice way to split up concerns. In React-Router-Component, the RouterMixin [1] mixes in the Environment Mixin [2] which allows the Environment to address its own concerns in a separate file and to be included in other, custom components.

1. https://github.com/STRML/react-router-component/blob/master/... 2. https://github.com/STRML/react-router-component/blob/master/...


Ah, now I get it, you meant nested mixins. Great, thanks for the pull, hope it gets merged.


I've submitted a fix for this in react-mixin here. https://github.com/brigand/react-mixin/pull/22


Meh, mixins are anti-pattern and I am glad they are finally gone. In my experience mixins just make your code hard to read.


I never understood this line of reasoning. Isn't composition over inheritance a valid principle, especially in JS land?

Speaking more to the anti-pattern part of your comment, obviously whether or not you think they are hard to read is subjective.


Agreed 100%.

I find inheritance much harder to reason about or even read. Mixins don't always lead to the clearest code, but they're better than all the alternatives.


I don't think that avoiding mixins implies inheritance. The more common pattern, at least in React, is "higher-order" or "wrapper" components where the responsibility for managing the mixin's behavior is moved into a separate, composable component.

The main issue with mixins is that the origin of behavior becomes opaque. If I call this.mixinFunction(), it's not defined in my file or imported directly, so I have to know exactly which functions come from which mixins. With higher-order components, you can just look at the props and know where things originated.

I'm not a staunch defender of any particular approach, but I think that's the main argument against mixins. (And it applies to other languages as well, such as Ruby.)


Mmm, not sure I see a huge difference between:

    import Foo from './foo';
    let Bar == React.createClass({});
    Bar = Foo(Bar);
    Bar.mixinFunction();
and:

    import Foo from './foo';
    let Bar == React.crateClass({mixins: Foo});
    Bar.mixinFunction();
In both cases I'm adding functions to my Bar component; in neither case is it defined in my file or added directly.

It is true that in the general case the mixin approach would mutate the internal state of Bar, whereas the higher-order component approach would re-render Bar with updated props, which is a solid win for the latter style. (Conversely, a mixin can check the state of the underlying component, while a higher-order component cannot, which means that you can't really implement shouldComponentUpdate as a higher-order component.)

But it's really a fairly subtle difference, and I wouldn't say that either is particularly more transparent. :)


Most stuff I've seen is using decorators to enhance components (which seems like a better practice than mixins)


Does anyone have an example of an open source project that uses babel for react + es6? Usually for me the hardest part is setting up the project organization and plumbing to make everything work.


This one looks pretty reasonable: http://jmfurlott.com/tutorial-setting-up-a-single-page-react...

I recommend avoiding gulp and grunt and any other build systems. They're completely unnecessary. npm and webpack are sufficient. npm works well as a simple task runner, and there are webpack plugins to do pretty much anything you'd ever do with grunt or gulp.


Cheers! this looks very helpful.


For a full and complete example take a look at one of my most recent projects :) https://github.com/lhecker/se2-bga

I'm currently studying computer science in germany. In a team of 5 we created the above project for a software engineering assignment. But in the end I wrote the entire code part alone. :D

It implements a simulated elevator and displays the internal state in a UML state machine diagram.

It features:

  - Grunt build system
  - JSX + ES6 to ES5 transpiler using babelify and browserify
  - LESS to CSS transpiler
  - karma + jasmine test system
  - live reloading ("grunt serve")
  - building a static page from the source code ("grunt dist")
  - building a nw.js based app from the static page ("grunt build")


I setup a repo [0] with a boilerplate that actually covers all the bases for a real web app, because I realized just how annoying and difficult it could be to get something setup. [1]

It provides an environment for development, testing, and production environments. In development, hotloading / live reload of assets when possible, and refresh otherwise. In production it'll do proper cache busting and asset minification. While testing it generates code coverage!

Best part? No gulp or grunt. It's all basically a heavily commented webpack config and a few npm scripts.

All of the people that have responded to you so far seem to disregard at least one of the details that I consider important. Mainly, it should have all the tasks needed for a web app that you plan on working on for a period longer than a few days, and it shouldn't make you deal with more build tool bullshit than is necessary.

I don't have any examples of big projects using web-app without modifications, however, I have a small example: quad-blog [2], which is my blog. It's written with fluxible, and the webpack config for that project is based on web-app. It takes it a step further and does isomorphic (or universal) javascript, so it'll do server-side rendering and then delegate to the client once it's loaded. One other highlight of the project is that it uses Koa, so you get real middleware (as in, middleware that behaves like a stack). Oh, and it uses Sequelize and shows how you'd do database migrations with an awesome relational database: Postgres, instead of taking the NoSQL shortcut (which is woefully inadequate for a lot of applications).

[0] http://github.com/cesarandreu/web-app

[1] https://blog.cesarandreu.com/posts/a_reasonable_starting_poi...

[2] https://github.com/cesarandreu/quad-blog/


I created a quick-start ES6 React repo that takes care of the basic organization and plumbing of Gulp and Webpack.

It allows you to immediately start writing ES6 code for React without the spending hours setting everything up.

It's a work in progress, and any feedback would be appreciated!

https://github.com/mrblueblue/react-quickstart


At Meteor, we're working on solving exactly this problem. We're currently working on a painless integration with React that lets you just add a package to get full-stack data sync, JSX compilation, etc.

Check it out: http://react-in-meteor.readthedocs.org/en/latest/

(I work at Meteor)


Have a look at redux, it showcased both creative approaches and solid examples with ES6/7 features.

https://github.com/gaearon/redux/tree/master/examples/todomv...


I tried the webpack getting started tutorial [0] and just switched the css-loader in the tutorial for the babel-loader.

Just took me half an hour from start to getting react+ES6 running.

    [0] http://webpack.github.io/docs/tutorials/getting-started/


Atom does I believe, but their build tool is really complicated.


Atom uses CoffeeScript, but Nuclide[0], Facebook's suite of packages for Atom, uses ES6/7 (including async/await) via Babel. The transpilation and caching of transpiled sources is done in the nuclide-node-transpiler[1] package.

[0] https://github.com/facebook/nuclide

[1] https://github.com/facebook/nuclide/tree/master/pkg/nuclide/...


I'm using React in ES6 with Rails (the react-rails gem now uses Babel as its transpiler). What I've found is that I've had to choose between using ES6 and getting prerendering working correctly. I also couldn't get the ES6 modules working without RequireJS or CommonJS. If anyone has this figured out, I'd love to hear it.


I have it figured out. A long-winded explanation:

Honestly I hate the react-rails gem. Whoever was maintaining it kept doing things at the whims of issue requestors. I remember one instance where they broke our apps with an upgrade because someone decided it would be a good idea to shim a definition for `window` into server prerenders. All because an issue creator who didn't really know what they were doing supposedly "needed" that to get browserify-rails working.

So we made this: https://github.com/revelrylabs/execjs-rails. That handles the server-side rendering for us. We only use react-rails for its assets, never for its helpers.

And here's our own (always-evolving) layer on top of execjs-rails: http://toolkit.revelry.co/pages/core.

Examples are written in dusty JavaScript, but we've successfully used revelry_core with sprockets-es6 several times now.

EDIT: Still no modules yet. It doesn't help that Josh Peek deleted the old sprockets-es6 repo and all its issues before passing off maintenance to someone else.)


Wow! Thanks for this. I've been wrestling with getting ES6, React, and Rails to play nicely for some time. How stable is execjs-rails?


Very, actually. It's about time I add more tests, maybe remove its opinion about what view context to dump to JavaScript (leave that to the end dev), and version it as 1.0. I think it's had one significant bug in almost a year and no problem issues in the past 6 months.


Ha, so mere days after I told you it's stable I had to ship a fix to make sure that it was serving precompiled assets when they are available. We had never noticed because our server-side assets had never gotten large enough to go over Heroku's 60-second boot time limit. So anyway, if you're trying this out, please upgrade execjs-rails now. We cut our app's production boot time by roughly 80% by doing so.


It's been a little while, but I have modules working using the browserify-rails gem which provides CommonJS support to sprockets via browserify. I use Babelify for ES6 support and then Reactify for JSX support. I add a command line argument to browserify in my application.rb to do all the transforms--config.browserify_rails.commandline_options = ["-t babelify", "-t reactify"], and it spits out working ES6 React.


There's always the sprockets-commonjs gem, but it requires sprockets ~> 2.0 (sprockets-es6 requires sprockets ~> 3.0).


Yeah, I'm using the sprockets-es6 gem.


https://github.com/justin808/react-webpack-rails-tutorial

Here's a tutorial on how somebody integrated webpack, react, and rails.


Looks to be a nice improvement. The only thing that really bothers me is if they deprecate componentDidMount. I think it's a lot more verbose than using the constructor method, especially given the corresponding componentDidUnmount method still exists. Is there a destructor syntax for ES6?


The constructor takes the place of componentWillMount. I believe componentDidMount is still used.


Looks like getInitialState is absorbed by the constructor as well.


Was about to panic - what did sebmarkbage blow up this time?


I haven't found any information on how to use libraries that depend on mixins for ES6.

Say React-router, how would you use that if you're extending a class in ES6 and need to rely on that mixin?


Since mixins are not supported in combination with classes[1] there is no way. I just fall back to React.createClass when I need mixins (afaik this is also what Facebook does).

A lot of libraries, including react-router, are considering decorators as an alternative.[2]

[1] http://facebook.github.io/react/blog/2015/01/27/react-v0.13....

[2] https://github.com/rackt/react-router/issues/1173


Thanks! I suspected so, but I wasn't sure. I've found that you get a lot of messy variations when doing ES6 compared to sticking with ES5 or CoffeeScript.

Not to mention the issues with all the god damn different build tools, it gets hard to get something standardised and good.


The react-starter-kit is a great way to dive head first into ES6 and React. Just clone the repo, npm install and go. It's fully up to date with all recent React and ES2015/2016 goodness.

https://github.com/kriasoft/react-starter-kit


More Javascript `this` juggling. I really want to write a wrapper around `createClass` which just passes things as normal arguments.


These new syntactic sugar additions are great for lazy fat-prone people like me :)


where is the outrage over jsx syntax? why isnt anyone screaming for json now? is the bandwagon late?


C'mon.

> Right away, you'll notice a subtle difference – a more terse syntax is available to you when defining classes:

    // The ES5 way
    var Photo = React.createClass({
      handleDoubleTap(e) { … },
      render() { … },
    });

    // The ES6+ way
    class Photo extends React.Component {
      handleDoubleTap(e) { … }
      render() { … }
    }
It may or may not be more terse in longer examples, but ES6 already supports things to make the class syntax less terse here by about the same margin the article claims.


While it doesn't add up to a terribly large amount of extra characters, you are missing the function keyword (ie. `handleDoubleTap: function(e)`) in the ES5 example.


Ah, now I think I understand what they were trying to argue—full ES5 versus ES6 where I took it to be ES6 versus ES6-using-class.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: