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:
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.
"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.
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.
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.
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.
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.
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.
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.
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 :)
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.
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.
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.)
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. :)
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.
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.
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).
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.
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.
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.
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.
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.)
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.
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?
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]
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.
> 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.