Hacker News new | comments | show | ask | jobs | submit login
Removing User Interface Complexity, or Why React is Awesome (jlongster.com)
632 points by jlongster on May 13, 2014 | hide | past | web | favorite | 219 comments



This is a really thoroughly researched post and jlongster has my gratitude for writing it up.

I have two concerns with this approach. Take everything I say with a grain of salt as one of the authors of Ember.js.

First, as described here and as actually implemented by Om, this eliminates complexity by spamming the component with state change notifications via requestAnimationFrame (rAF). That may be a fair tradeoff in the end, but I would be nervous about building a large-scale app that relied on diffing performance for every data-bound element fitting in rAF's 16ms window.

(I'll also mention that this puts a pretty firm cap on how you can use data binding in your app, and it tends to mean that people just use binding from the JavaScript -> DOM layer. One of the nicest things about Ember, IMO, is that you can model your entire application, from the model layer all the way up to the templates, with an FRP-like data flow.)

My second concern is that components libraries really don't do anything to help you manage which components are on screen, and in a way that doesn't break the URL. So many JavaScript apps feel broken because you can't share them, you can't hit the back button, you can't hit refresh and not lose state, etc. People think MVC is an application architecture, but in fact MVC is a component architecture— your app is composed of many MVCs, all interacting with each other. Without an abstraction to help you manage that (whether it's something like Ember or something you've rolled yourself), it's easy for the complexity of managing which components are on screen and what models they're plugged into to spin quickly out of control. I have yet to see the source code for any app that scales this approach out beyond simple demos, which I hope changes because I would love to see how the rubber hits the pavement.

It's always interesting to see different approaches to this problem. I don't think it's as revolutionary as many people want to make it out to be, but I've never been opposed to borrowing good ideas liberally, either. Thanks again, James!


Thanks for the rational response, Tom. I hope this doesn't get buried (someone is going through and downvoting at least all of my comment to 0).

Blog posts are best when they are sensational, and I try not to overdue it. I think React has a lot of good ideas, but "revolutionary" is a strong word. I think "refreshing" is a better word. Regardless, I think both React and Ember are the best 2 solutions out there right now, with quite different philosophies, and I'm happy that users have a choice.

Using rAF in my post was pretty much a hack. I think it was fun to take that and run with it. When you use React though, you don't actually do that, you use its `setState` method, or you use something like Cortex. If you look at my cortex example, you do use setters and getters, which give you a way to notify data change. Why don't we just use models like Ember? Because React still doesn't care how we model our data -- even if we have to call `set()` to trigger a paint update, what we get is the choice to use something like persistent data structures for our models.

=== I was completely wrong about Om, it does not continuously trigger rerendering/diffing ever 16ms with rAF. It only uses rAF to batch rendering, so multiple repaints are throttled to a minimum of 16ms ===

The on-screen issue is interesting; I need to think about it more to see if we can actually leverage it in production apps. I think we can for large list views. You don't share scroll state, do you? I absolutely agree that too many JS apps are breaking the web, and I love that Ember has defaults to make that not happen. There is a grave danger in using React and not taking care to do things right.

I'm actually really, really happy about the idea of React and Ember being the 2 ways to choose to build webapps. I have the upmost respect and love for Ember, I think it does a lot of things right, and I wouldn't be surprised if things like routing wasn't copied for libraries to use for React. <3


I think this technique is really cool but I thought I should point out that although continuous rAF makes it easy (you can set state directly), on but FF and Chrome on my machine, even when your page appears to be completely static it's consuming 10-20% of CPU constantly.

That's got a couple of issues.

1. It eats my battery

2. It DoSes my machine (10-20% not available for other things)

So, please don't do that. Set a `dirty` flag, call a `setState` or something that requests just 1 rAF or queues a task to re-render or something and then go back to sleep.


It's really not meant to be something to use in production. It was fun to run with it, but you're absolutely right. In fact, if you look at my Cortex example I do just that. You will most likely want to use a data structure that knows when something's changed anyway.

But it was a neat way to go from something very simple to more complex.


it's consuming 10-20% of CPU constantly

It appears you're using a multicore machine with between 5-10 cores. A continuous loop is basically going to keep one core at 100%, which is only a bit of an annoyance with a multicore, but on a single or even dualcore machine (e.g. low-end mobiles), it will make everything else slow to a crawl.

It's interesting to note that, were this done several years ago or earlier, it would only make people complain about how your site froze their browser, but now we barely notice a single core running at full load unless we're observant...

Please use computing resources responsibly.


A continuous loop is basically going to keep one core at 100%, which is only a bit of an annoyance with a multicore, but on a single or even dualcore machine (e.g. low-end mobiles), it will make everything else slow to a crawl.

Not to mention that, even on a high-end laptop, that will drain the battery very quickly and burn your lap in the process.


It's not really using 100%. rAF means they do their work, then it goes to sleep until the next vblank. They then get their rAF event, check if they want to make any changes to the DOM, queue another rAF and then go back to sleep. So it really is only 10-20%. But it's still 10-20% :-(

I would be curious why it's at 10-20% though. If they don't touch the DOM and their checks are quick (just a pointer as the article says) then there's some crazy serious overhead in the browser or somewhere just to call into JS once every 16-17ms and have it go back to sleep.

It would be interesting to look into where 10-20% is going. It seems like in a perfect impl, a mostly no-op rAF should take 0.001% or something along those lines.


To clarify, Om does not "spam" state change notifications via requestAnimationFrame - all rAF calls are batched. For example if a state change occurs we schedule re-render via rAF. If another state change occurs we will not call rAF since one is already queued. In fact no state changes can queue another rAF until all changes in the current cycle have been completely flushed.


I think I said that it did in my post, and I was wrong. Will update


I guess this discussion hinges carefully on our relative definitions of "spam." ;) What I mean to say is that, changes or not, the browser will be invoking your diffing algorithm every 16ms.


It will not be invoked every 16ms, my comment above was an attempt to explain that.


Won't that only happen if a state change has been made? That is, the diffing algorithm will only get invoked once every 16ms if the state changes faster than once every 16ms.


Nope, it calls it regardless of state change—that's the point, you eliminate the challenge of determining when state has changed.

To quote TFA:

> A set method to change state could trigger a rerender (React has setState), but there's an even easier way to react to changes: continuously call renderComponent with requestAnimationFrame to repaint the UI, and only change the DOM when the component returns different content.

Edit:

I was mistaken about how Om works. I was under the impression that Om scheduled a rAF every 16ms to check for state change. In fact, it only schedules a rAF once the state changes.

However, this relies on being able to listen for state change from the underlying model data. I was under the impression that one of the benefits of Om/React was that you could use its data bindings with any JavaScript library, even if it hadn't been instrumented for property observation. Instead, it seems that with Om, you are limited to consuming data structures that implement its state change notification interface.


Your conclusions about how Om works are still inaccurate :)

There is no such limitation about what data structures you can use. There is no state change notification interface for data. Components can update their local state - no notification required here. Updates to global information (the application state) triggers a re-render from the root component of the application. Because of persistent data structures these updates can be done in logarithmic time as we never compute React UI subtrees that depend on unchanged data - it's just a reference equality check (JavaScript ===) in ClojureScript for any given piece of data to know whether it's changed or not.


Thanks for clearing up the confusion. Although, I think it's worth it for you to edit your initial reply since it's the most upvoted comment so far.

Also, your comment, to me, shows there is still some confusion regarding Om's internals:

> However, this relies on being able to listen for state change from the underlying model data. [...] Instead, it seems that with Om, you are limited to consuming data structures that implement its state change notification interface.

Actually, the interface used is ClojureScript's flavor of STM: you set your app state, generally a hash-map, in an atom. When you mutate the app state via `swap!` it is published to Om -> React -> render. This may seem like a pedantic distinction, however, the key point is that you are required to use an atom which controls app state mutation. You could also use strings and vectors as your app state if you so choose.


Interfacing with an external js library that publishes changes would be trivial though. Typically if you're building a ClojureScript app you're building a ClojureScript app... which means using atoms.


That's a description of the examples that use "Bloop," jlongster's toy library. Those examples do run a continuous requestAnimationFrame loop.

Om, however, does not call requestAnimationFrame in a continuous loop; it calls it only when the state changes.

(To be fair, jlongster's article originally said that Om also rendered continuously, but that has now been corrected.)


He's describing using rAF essentially as a form of throttling, to make sure you render at-most once per frame, but usually much less often.


I think a lot of people see frameworks like Ember and Angular and get scared by their vastness. You don't "get" them in one evening. I have spent many hours poring over documentation, articles and videos for both Angular and Ember and I still feel that there's more to learn. But things like routing, data persistence and controllers will be a part of your app even if you use React.

What I find good about Ember/Angular is that they are very particular about how your app should be constructed. When I started writing single page JS apps, I didn't know what the best practices were. If I had started with Ember, I would've learnt. If I had started with React, I would have been making it up as I went along. If you know what you're doing, maybe that's good. For me, I find that I really like having Ember tell me how to structure my app.


That's a very good point. I've currently settled on Backbone to give my stuff a bit more structure, but I suspect some of the complication of construction might actually disappear when using React. Not all of it, of course, but some of it.


You'll find a surprising amount of it will simply disappear. I'm at the point where I removed my models and collections directories entirely; since the only feature they provide me at this point are getting data from the server (which I can do with just jQuery, superagent, etc.)


And then you manage it in what way?


In a simple React app (ie most apps), you end up storing all your models (as Javascript Objects/Arrays) in one single scope (the "App/Main Component"). As a result you don't need to share things around / access them / listen to them from many different files. They no longer need "managing". I hope that helps.


I would be nervous about building a large-scale app

I have a Javascript game client that does rendering optimization by comparing a 79x25 grid of numeric values with JSON data it receives from a server. That is just short of 2000 items, and it is enough to stymie older versions of Firefox running on Core Duo machines. I also queue things, and in fact, the "diffing" and the rendering happen in two different rAF frames, and it's still a challenge for older versions of Firefox running on Core Duo machines.

I wonder if this sort of benchmarking been done on different machines and different versions of the various browsers?


In the case of Om, I believe the immutability of clojure helps out and makes the diffing of databound elements a simple (non-deep) compare.

You can end up making an app with quite a number of elements flying around.

A neat pixel editor example: http://jackschaedler.github.io/goya/


As mostly an outsider to the web front end development, React.js is probably the easiest one for me to understand among the typical "frameworks", especially Angular and Ember.

After all the excitement about Angular for example, I went to learn about it and just got lost with new concepts: DOM transclusion, scopes, services, directives, ng-apps, controllers, dependency inversion and so on. I can use it but need someone to hold my hand. It reminded me of Enterprise Java Beans.

But so far just learning how React is put together and looking at the tutorials it seems like less of a framework and easier to understand altogether. I suspect this might become the new way to build web applications.

Well anyway, don't take this too seriously, I as said, I am an outsider to this.


> After all the excitement about Angular for example, I went to learn about it and just got lost with new concept DOM transclusion, scopes, services, directives, ng-apps, controllers, dependency inversion and so on. I can use it but need someone to hold my hand. It reminded me of Enterprise Java Beans.

AngularJS has a serious "naming" problem.

Most these concept are easily understood when explained the right away,what AngularJS doc doesnt do. The only complicated thing to grasp is the digest cycle. But anything else is trivials.It's nowhere near the complexity of Java EE.

Scopes are easy,like any composite structure you have nodes with children and parents ,what make scopes special is that they can inherit properties from their parent scopes.

Directives are just custom html elements/attributes where you should do dom manipulation,all other angularjs components should be free from any DOM manipulation,Directives are the closest thing to react components.

Controllers represent the state of the view,when the data in a controller changes, a view that exposes that data changes and vice et versa.

Services are dumb objects that can be shared between controllers and dependency injection is the way one share these services. Controllers can references services ,and services can reference other services. Services are singletons

So there is nothing really complicated with all these concepts,just that the doc sucks for some reason.


As the famous quote goes, there are two hard things in computer science: cache invalidation and naming things. When I first heard it, I thought it was a joke; nowadays I feel like it's barely a simplification.


"And off by one errors".


I think coming to see that "joke" as deadly serious is a coming-of-age moment for all programmers.


I agree. It takes a while to get one's head wrap around AngularJS. But once you get it, it's awesome. Anyways, this is the tutorial that finally helped me get it:

http://www.thinkster.io/angularjs/GtaQ0oMGIl


Great explanation.

Angular attribute directives would map well to React Mixins. They take more work to set up, but with mixins code can at least be reused outside of the inheritance tree.


I feel your pain. I'm a backend guy who has to learn front end all of the sudden. To my mind, React just makes sense. I understand that other modern frameworks like Angular and Ember "make sense" as well, in that they're current best implementations of well-understood best practice, but from my outsider perspective, it looks as complicated and baroque as Catholic theology. Yes, it's all very beautiful and such, but I don't know if I'll ever be able to instinctively grok it.

React? I grok that.


If you're a backend person, thinking about Ember as being more of a Smalltalk MVC than a Rails MVC helps a lot.


Libraries like angular and ember are for programming in the large, with lots of code and lots of developers sharing that codebase. They trade simplicity for scalability. You should use them if you know you need them, and if you need them you'll know.

I went through this transition in late 2007, where the app my team was building gradually outgrew simple javascript libraries, and i ended up adopting extjs (the ember of its day) at great cost, but to great benefit. It is 600 kb of js code uncompressed just for the framework, and we not only ended up using all of it, but building a ton of code on top. We needed all that complexity to build the app we work on, but then it is over half a million lines of code by now. If you don't have those needs, the big js frameworks can be more trouble than they're worth, sort of like j2ee vs php.


Angular is huge bloat. Unfortunately Google's name is behind that mess so it will live for little bit longer before getting forgotten.

I myself prefer frameworks that are minimal, least invasive and plays nicely with pure JS/HTML instead of treating them as bug. So anything that requires me to call .createClass to create an instance is out. Personally I've used Knockout.js pretty successfully. I think any average js dev can understand that framework in 15 minute and be productive. Although it's not perfect if you you are looking for idealistic MVC implementation.


KO is not a framework it's "just" a data binding library


I've been doing Angular for about a year now and am pretty comfortable with it, but I definitely remember going through that brick wall and see it every time I try to explain it to someone new. React looks much more straightforward to pick up but I am curious whether someone who has "mastered" both would find one or the other more powerful or maintainable.


I haven't "mastered" React by any measure, but I've been using Angular for quite some time, and I find that apps written with it become really frustrating to maintain after a certain amount of complexity. I see Angular somewhat akin to C++ in that it's the most powerful and flexible (IMO) of the popular JS frameworks, but you're also going to spend a hell of a lot of time creating your own structure and conventions. This is a fine tradeoff if you need the flexibility, but for my use cases, React is much simpler and less headache-inducing to use. I just find that I can fit React's model into my head, whereas with Angular I'm constantly needing to figure out how to translate my mental model of my app into code that actually works, and dealing with weird, undocumented edge cases.


There's really nothing to 'master' about react, that's the beauty of it really. You just learn about react's view of how data flows through an app with props and state; and that's pretty much it.


Exactly. React is a fairly simple library that can play well with other libraries, including on the server-side. Angular and Ember are complex frameworks.


Yes that is, I guess, what I like about!


Not to distract from the topic, but jlongster's posts should be a case study into how to make an effective demo/tutorial on the web. The side by side code/demo format is very well done and should be the de facto way to do code + demo. There have been so many times when I've been reading a tutorial and click on a demo link that opens a new tab. This makes me completely lose context as I switch back and forth between the tutorial and various demo links.

For another example of a post that takes advantage of the dynamic nature of the web page, check out jlongster's sweet.js tutorial[1]. It's a tutorial on writing macros with JS that you can actually interact with (you can make modifications to the example code snippets and see your macros expand on the fly). Very cool.

[1]: http://jlongster.com/Writing-Your-First-Sweet.js-Macro


As a recommendation to the author, it would make sense to show the example/demo area the whole time, not only once I scroll down. It confused me. A lot.


Agreed, I really like the demo area but it's a bit of a shock when it first shows up.


Heh, it's been mixed reactions. I will probably tweak the initial experience, but will need some time because I can't leave it open on load because it blocks the header.


I thought it was nifty. The shocking aspect might just be the big layout change. Perhaps a notification ("Check out the demo") so the user has to click it to enable the side pane, and then its business as usual.


I liked the layout as well. One thing I would change would be to make the code area wider than the demo area, as some of your lines wrap, where the demo area rarely needs a line break.


It's a pretty crappy experience. I'm reading an article, suddenly the text decides to move left for 'no good reason' to create a narrow but empty sidebar.

WTF? I don't like reading things on the left side of my monitor, so I make the window wider to try and put the text back in the middle. Except now the demo area gets even wider (why? you don't use it for anything but tiny things?).

As I scroll, the various iframe loads create annoying jank, and to top it off, there's a bug at the end of the post where it moves horizontally for no good reason.

If you're going to do stuff like this, you need to polish it waaay better. This reminds me of the UI animations in the new Firefox. A good idea ruined by implementation, would've been better to leave them out.


That demo area sliding out actually caused me to actually read the article. I was just about to close it with "meh, react"


Sometimes a shock is good. I took it as, "Hey, this page just gained new abilities." Then I clicked and moused over the square and the triangle to see what they were about.


Agreed 100%

Desired Reaction: Oh cool, a demo popped up just when it was needed.

My Reaction: Huh? Ugh, that's annoying. Wow, and I scroll back up and it moves again; I didn't ask for that either.


For those that haven't tried it, David Nolen's Om for ClojureScript is an excellent React framework.

https://github.com/swannodette/om

I've not used vanilla React, but Om is certainly fantastic and apparently adds a bunch of stuff that's not in the JS version.

Also, a web framework written by the guy that wrote most of the language you're using? Win!


I would love to support a JS project that is something like a port of OM to JS.


I understand that there are sometimes practical reasons for not being able to use ClojureScript, but have you given it a go? It's really very, very nice (much nicer than JS in pretty much every way).

* Immutable data (you can get some of this in JS with Nolen's Mori http://swannodette.github.io/mori/)

* Better functional programming than Underscore (map :mykey some-objects)

* Great syntax: homoiconicity, thrush operator, first class set, regex, map, vector syntax

* Macros!

* Use of cool frameworks: Om, core.async

* Same language as back-end if using Clojure

It was quite frankly intimidating to get started with it all as an ex-Java/Obj-c/Python/JS dev but I could never go back.


I've been trying to move towards ClojureScript for a while, but there are so few introductory resources out there that allow you to navigate between the Clojure world and the JavaScript world in a way that makes sense to people who come from JS backgrounds exclusively.

I wish OReileys would issue an expanded version of their Intro ClojureScript book!


I've been learning CLJS for a couple months. Here's a syntax guide and a list of resources I've used: https://github.com/shaunlebron/ClojureScript-Syntax-in-15-mi...


After browsing around, you're GitHub repo is a learning treasure. Thanks for posting all of that stuff in such a clear way.


Thanks so much for posting this! I haven't found anything this concise before, with such a specific target.


It's definitely a lot to take on. I'd probably start with just plain Clojure to learn the syntax and how to do functional programming, then look into ClojureScript.

Get comfortable using Lein and editing your project.clj, then check out this plugin:

https://github.com/emezeske/lein-cljsbuild

It's a big investment but learning Lisp will repay you. There's tons of classic CS literature that you'll now be able to unlock and immutability really is the future, so it's good to start getting acquainted with it.


Totally. Since I started following React and digging into various links and resources the FP paradigm is really starting to make sense in terms of long-term benefit. Time for the next step, however.


it's really unfortunate clojurescript is not written in javascript (or clojurescript, like coffeescript compiler is written in coffeescript ). I wanted to integrate a lisp to a toy jsbin app (https://mparaiso.github.io/playground/), but no way, right now i'm using outlet. See the use case? clojurescript is never going to be big in javascript land if one cant compile it in the browser.


I agree that a self-hosting ClojureScript compiler is desperately needed and highly desirable.


We'll get there (we're not so far as it is), but it's just not high enough on anyone's priority list yet.


Looking forward to that. I'm a JS dev who learned Clojure through Clojurescript (and D.Nolen's blog). In trying to entice my colleagues to try it, the JVM bit seems to be a bit of a barrier... but the LightTable development loop blows them away.


OM and ClojureScript are great - but it is all about choice. Sometimes i prefer/need JS as a language.

It would be great to get the AMAZING clojure-community ideas into the JS world.


Yep, camus2 points out environments like jsbin. Bookmarklets are another place you wouldn't use something like ClojureScript.

I'd argue once you go beyond "small" things though switching to ClojureScript is preferable to duplicating large parts of its functionality in separate JS libs.


I've been building a FP style framework very similar to OM & Elm in plain javascript ( https://github.com/Raynos/mercury ).

It has some of the core features

- immutable data - immutable vdom - global state atom, no hidden local state. - no manual DOM manipulation code (read or write). - a single top down flow of data from input to output - Events and Signals from FRP that can be manipulated using pure higher order functions.

etc.

As a bonus it's very modular, so if it doesn't fit your needs at least some subset of it will.


I really like the core concepts of React, especially the way it is designed to help you organize your code into reusable components.

I think the key to making React take off is building a centralized repository for components that are open source. Then building your webapp would be as easy as importing the components you need:

     bower install react-navbar
     bower install react-signup-form
     bower install react-sso-signin-form
I think this is definitely the future of how front end web development will be one day.


I'm working on an app that takes this idea a step further. It is a platform that lets people create apps by defining a data schema and UI components to edit and display this. Once an app/schema/component is defined, it can be "forked" by others and further customized. Think github not for source code, but live apps[1].

One of the key requirements for this was a way to run untrusted scripts client-side (server-side is somewhat easy), since the platform lets users write arbitrary UI components. React works wonderfully here (in theory); we can isolate the React component in a sandbox (iframe with sandbox attribute set) and copy the Virtual DOM back to the main window after sanitization.

Add:

The beauty of React is that the developers recognized the limitations of other approaches; components in web apps cannot be solved with a rehash or an improvement on existing ideas. Giving up the usual design patterns and DOM hackery in favor of an esprima-based Javascript parser and serious Math is some creative thinking.

1: Open source, will have an alpha in 3 weeks: https://github.com/jeswin/fora


That is pretty interesting. So using Fora you can jumpstart a new app by defining all your data models, and then select a bunch of components to build a skeleton view that makes use of those models?

If so this will be very useful, especially since it sounds like it will allow us devs to spend more time on the business specific logic, and making the interface beautiful, instead of spending lots of time gluing together components and models.


Yup that is what it is. It builds on the notion that many apps are actually forums, with various levels of customization. Flickr, Pinterest, HN and even Amazon and Tiger Direct (TigerDirect will have products, reviews etc as 'posts') are actually forums. So we use the term forums and apps interchangeably.

The social aspect is equally important:

- There are millions of developers who don't participate in improving apps today because creating and hosting an app isn't a friction-less process. On Fora, if you see an app/forum that fits your needs, click fork, edit some JS+React/JSX in the browser, and you have a new app.

- Everybody sees all source code for all apps/forums; so it's great to learn. And then improvements help everybody. Like wikipedia for code. .

- Many people know enough JS to tweak stuff. React mostly takes just JS knowledge, so you don't need to know the framework like Angular. Ah, and also isomorphic UI code that runs on the server and browser. Also for all it's issues, one thing JS has going for it is that you can read and edit in a browser.

Ah there; I got excited. :)


So I have a word of caution. As someone else in the thread mentioned, React is very intuitive for beginners. There's another framework I've used that was also intuitive for beginners: Backbone. The reason why Backbone is inferior to Angular and Ember is because it optimized for the beginner. Angular and Ember are optimized for the experienced developer on a large code base.

Specific to your suggestion, which I think is awesome, is the idea of composibility. The easiest kind of component to write is a large component with lots of options, like jQuery plugins. This is the hardest kind of component to use outside of its intended use case.

What makes Angular so good is that the core directives are all extremely composable. They can be used all over the place without hacking.

To make your dream come true we as component authors must design carefully to make smaller, more focused tools, rather than large components, because large components are harder to adapt to applications outside their main use case.


React has been designed to work in Facebook's codebase, to build large features worked on by many experienced developers. The fact that it is intuitive for beginners is a side-effect, not the primary objective.


Don't forget that Facebook invested a what I would call inproportionally lot in the PHP ecosystem primarily to let new employees pick up the pace as fast as possible.

I wouldn't be surprised if React was kept intentionally newbie-friendly, too.


While it isn't impossible for a complex library to become popular, I would be very surprised if a library/framework wasn't kept intentionally "newbie-friendly".


Yes + Instagram web (which is of course part of FB)


Curious why you think Backbone is optimized for beginners as opposed to Angular. I get that Backbone and React have fewer concepts to learn and thus are more approachable. But if you're building serious applications I'd say Backbone and React require MORE experience, because there are fewer choices made for you than Angular (and especially Ember).


I would agree; Backbone and React are tools that help you do the job, but they don't decide how the job is done. That's up to you. Angular is like the cookie-cutter.


Totally agree here, but this too is a double edged sword.


Surely this doesn't have anything to do with react though? Bower[1] or Component [2] will do this.

[1] http://bower.io/

[2] http://component.io/

edit: the parent comment originally referenced a theoretical `react` command and didn't mention bower, which is why I brought it up.


Bower and component are more like package managers. GP is talking about a library of re-usable user interface components.

Unfortunately, my best attempt at an analogy is Visual Basic controls, which might not be a great precedent, but the idea itself is a good one.


Well they just edited their initial post to specifically use a `bower` command rather the theoretical `react` command, so I'm not sure. What would the different be between your VB-style controls and something like this confirmation popup:

https://github.com/component/confirmation-popover


React has a much richer notion of what a 'component' is. To date, most JavaScript libraries lack shared assumptions about how you will build your UI. jQuery plugins make only the extremely minimal assumption that you will apply the plugin to some DOM element - beyond that, how the plugins behave, how they manage their state, properties etc. is not defined by any standards or even assumptions.

The confirmation popover you link to is a good example. It's a black-box component which exposes a fairly minimal interface. The constructor for this component works like this:

  new ConfirmationPopover(msg, [title])
To attach the popover to an element you need to do:

  popover.show(el, [fn])
However, if we take another component from the same library, the swipe component[1], we see different conventions. Its constructor:

  Swipe(el)
It also has a show method which takes totally different parameters:

  .show(i, [ms], [options])
This is why I describe such systems as package managers or library managers - they're just a way of importing and exporting code and don't do anything to aid reuse. They're not particularly likely to play well together, lack standard interfaces and are almost certainly not composable in any meaningful way.

React components are different because React defines some standard details of how components behave, how to extend them, how to inspect them and pass data back and forth. Components can contain other components, and all components have a relative place in the render tree. This makes possible standard developer tools that can be used to observe and inspect components in a DOM-like tree structure[2].

So, you could certainly use bower to distribute React components. What's different about React isn't how the code is distributed but the fact that you can have expectations about how, say, a React photo gallery component would behave that you would not get from some other JS library.

[1] https://github.com/component/swipe [2] http://facebook.github.io/react/blog/2014/01/02/react-chrome...


Heh... was just in the process of updating my comment with Bower when you replied. I agree that this could work with Bower as the package manager.

However, it would be more convenient if there was a distinction between packages that are designed to be UI components, and packages like AJAX libraries, async, and other logic libraries, which are a better fit for bower.

Distributing the UI components via bower is doable, but it wouldn't be nearly as nice as a dedicated component ecosystem where it is easy to search and discover relevant React components.


Not even if bower let you search by component type or some kind of category or tag?


The best interface for a react UI component repository would be something that had information like:

    * A picture of what the component looks like
    * How large the component is in KB
    * Which CSS frameworks it requires or supports
    * Cross browser support information
Bower is a very simple package manager right now with little information about the package beyond its name, a line of descriptive text, and a link to the Github.

Overall the experience would be better for React devs to develop a customized package manager interface well suited to the type of packages being delivered.

Of course there is nothing stopping UI component creators from distributing their components on both Bower and a React specific package manager, but I think for purposes of discoverability a React specific one would be better suited.


Yes definitely, although I imagine most components will be internal to your own applications as opposed to shared publicly. Web Components is a great model for publicly shared components but not sure how much value it adds for private components. If you are into the component based approach see parcelify and / or cartero as those tools could simply your build process.

https://github.com/rotundasoftware/parcelify/


what does React bring to the table here that Ember, Backbone, etc. don't? i could register my Backbone or Ember views with Bower all the same.


This comment from another HN poster does a good job of describing the difference between components in React and "components" in Ember and Backbone:

https://news.ycombinator.com/item?id=7738511

Long story short, React has a much more graceful system of making the components generalized instead of the adhoc system that Ember and Backbone use.

Ember and Backbone have features that are similar to components, but components from two different sources will rarely work well, because often one component will break another. Anyone who has tried to put a bunch of different Backbone views from different people together has probably experienced this pain first hand.

React is designed from the ground up to allow components to work well together.


Can you expand more on what you mean by two Ember components will "break each other"? This isn't something I've experienced when putting components together.

Can you also expand on what React design decisions has made vs. Ember that allow components to work well together? We've spent a lot of time thinking about creating a unified interface for Ember components, so I'd like to better understand where it's broken down for you.


so as i understand, the benefit is that React encourages standard I/O. but i also understand that nothing is stopping anyone from using a standard I/O with Backbone or Ember (which i recognize is why you say "from different people").

my point is that it's a people problem as much as a tooling problem. or is it impossible to build incompatible React views?

i'm currently working on a library that makes it easy to share patches (GUI included) for audio applications. i'm using React. one problem i struggle with is that without my own additional standard, nothing is preventing anyone from making a component that can't patch in. which is the same problem i would have if i were using Backbone.

if you're looking for a "standard" way to share components you need to make assumptions about what type of GUI you are building- not just how you are building it.


Ember already has what you describe as "standard I/O."


I experimented with React a bit but I was a bit bugged by how large it was. The basic idea of rendering to a virtual DOM and having unidirectional data flow is really simple but I had trouble actually diving in to React's source code and seeing things under the hood (for example, I had to find a blog to see how the diffing algorithm worked).

What are the other libraries out there that we can use for this virtual DOM pattern right now? I only found mithril[1] that similarly does the template rendering with Javascript but I still don't know how different to React it is in the end? Is the diffing algorithm similar? Do they handle corner cases the same (many attributes need to be treated specially when writing them to DOM)?

Simplifying it a bit: other than the virtual DOM, is the rest of React also the best way to structure apps? What would the ideal "barebones" virtual DOM library look like?

[1] http://lhorie.github.io/mithril/


While the basic idea of rendering to a virtual DOM is simple, making it work well for large applications require a lot more than a toy implementation as described in the article.

In order to get adopted, React needs to coexist with existing applications/third party libraries that do manual DOM mutations. The life cycle methods are there to deal with this.

React implements its own class system that supports mixins and type annotations. The plan is to change the API to use ES6 classes (we're working to improve the standard to support all React use cases).

React re-implements its own event system in order to make it fast, memory efficient and abstract away browser differences.

Making composable components is not as straightforward as it first seems. There are a lot of edge cases like refs, owner/parent to be handled.

Then, as you mentioned, there's the diff algorithm and batching strategies which need to be implemented in a performant and memory efficient way. And provide hooks for the user to be able to give it hints via shouldComponentUpdate.


Hi, Mithril author here.

I'm not familiar w/ React's implementation, so I can't speak for them. With Mithril, the diffing algorithm is basically a recursive tree diff. In addition to diffing at the attribute level (and taking care of some broken edge cases), it can do things like detect parent changes and reattach unmodified trees to new parents, if needed. I generally don't like corner-case-specific optimizations because I believe there are better directions to explore in order to improve performance (Mithril has a concept called SubtreeDirectives that I'm planning to expand on, for example). At the end of the day, one has to ask themselves if loading and parsing code to handle a bazillion rare corner cases is really significantly better than just doing the naive thing. The benchmark on the Mithril homepage seems to suggest that being minimalist performs better at the worst and arguably most important case (the first render).

Mithril in its entirety (with router, promises, ajax, etc) is ~500 lines of code (vs Bloop's 250) and the diff implementation has gotten more and more robust over the course of v0.1.* thanks to the Mithril community. I'd love to be proven wrong, but I'm seriously doubtful you can get a better balance between leanness and robustness elsewhere.

Re: best way to structure apps: I just posted an article ( http://lhorie.github.io/mithril-blog/an-exercise-in-awesomen... ) that ports some of the examples in this article over to Mithril to see how the two compared. My conclusion was that it's definitely possible to structure apps in a React-like style with Mithril. There a lot of benefits that this structure brings to the table, and using well understood design patterns effectively can go a long way to complement the componentization paradigm.

I don't force any particular implementation of the MVC pattern with Mithril, but I try to always organize code following the classic MVC pattern in my own code. My blog is partly an effort to document the techniques that can be used to support a liberal MVC pattern without necessarily committing to React's OOP paradigm or whatever.


I have a similar frustration with React. The source code is very hard to read our follow.

An ideal "barebones" virtual dom library looks like https://github.com/Matt-Esch/virtual-dom . The `virtual-dom` module was build out of frustration with the readability of react source code and is the minimal modular subset.

I've also built a small framework on top `virtual-dom` to add in essentials like immutable state and event handling ( https://github.com/Raynos/mercury ). Whilst mercury might not be the best way to structure apps, it's an approach that is getting me far and I'm drawing strong inspiration from FRP and FP systems like Elm and om.


Is there a single-file version of virtual dom available for download? I am not finding any instructions in the repo on how to build it. Also, why does it have so many files in the first place?


I opened this PR on virtual-dom ( https://github.com/Matt-Esch/virtual-dom/pull/67 ) to get a single file version into the git repo.

It has many folders because the `vtree`, `vdom` and `h` are fundamentally seperate concepts.

Again each one is seperated into it's own files, this allows you to just require the `is-x` functions or the `diff` function alone without having to depend on the entire implementation.

It's also easier to maintain code if it's not one big file.

There are plans to break vtree & vdom out

- https://github.com/Matt-Esch/vtree - https://github.com/Matt-Esch/vdom

Note `vdom` is an implementation detail, we could also write `vcanvas` or `vwebgl`


Please don't break the back button (Firefox and Chrome).

In Firefox 29.0 on Ubuntu 14.04, the left sidebar with the text of the blog disappears and is replaced with a white space. I do not experience this on Chrome.


I just tried it on Firefox 26 on OSX and could not replicate. It has worked for everyone I've had test the page. The only thing that happens when you press back is the animation to load the right demo. There might be something buggy with how the CSS animation is using your graphics driver?


Back-button breaking here too. Chrome 31/Ubuntu 14.04. It adds history without changing the URL, as the sibling poster mentioned.


Back button breaking on latest version of Chrome/Win7 here. Scrolling up and down adds history.


It adds history?? What is the URL changing to?


URL doesn't appear to change in chrome, but the back button just cycles through the various demo screens after you've scrolled down for a while.


Oh, that's because the demos are loaded in an iframe. Not sure what the best solution is, but I'll think about it. Thanks.


Whoa there. An iFrame? Why?


The second bug I mentioned only happens when I'm zoomed in 120%, which I am by default. Here's a screenshot: http://imgur.com/eDvLdMK

(As someone who doesn't work much with Javascript I thought the explanation was enlightening, BTW)


Add Opera to that list as well, or anything Blink based i would assume


He said he did not experience in Chrome. Is there any chance you could take a screenshot/screencast of the bug? I haven't been able to reproduce.


Great post. I recently started a project using reactjs, and I have nothing but good things to say. The unidirectional data flow, the declarative nature, and the virtual DOM makes it powerful and very easy to like.

The best resource is to follow the tutorial (link below). The tutorial explains everything you may have a question about when comparing it to Backbone, Angular, or Ember.

http://facebook.github.io/react/docs/tutorial.html

I also found the IRC channel to be very, very helpful.

The only downside is that you still have to rely on other tools to make a true SPA like routing.


I found this blog post to be very useful on how to leverage Backbone.Route with Reactjs.

https://medium.com/react-tutorials/c00be0cf1592


Would you recommend using React instead of Angular for JS heavy areas of a website that is built with a server side framework (like Rails, Django etc.)?

I developed a rather complex SPA with Angular recently and I cannot go back to the ghetto that is jQuery when using server side rendering.


Based on my initial explorations using React with Rails, I'd say React might even be better when used with an existing server-side framework.

With React, you can basically store all you data (state) in the root component (which could be the root of your entire page), and replace that with new state without thinking too much about the DOM updates and view changes that result from this.

This is perfect for a server-side framework, because such a framework by definition already renders everything whenever something changes (page refresh). Without React, the framework does a bunch of things and finally craps out objects that are transformed to HTML by the view (where the views are as 'dumb' as possible). With React, instead of rendering the object to HTML, you just pass these objects, as JSON, to a React component (which could be the whole page), and it figures out what needs updating. You don't have to deal (as much) with client-side logic if you don't want to, and things will still be performant.

This also significantly simplifies server-side rendering, to the point where it might require only one extra call to render the component server side (the handy renderComponentToString).

Of course, in practice it's often not quite that simple, but because of how React operates, you can get pretty far with relying primarily on the server-side framework and little logic on the React-side of things (plus you can achieve the 'holy grail' of seamless server- and client-side rendering.

(apologies if I'm getting things wrong, by the way. I'm by no means an expert on these matters and only just diving into React.)


Can you please explain how to store data from the server on a "root component"?

The data portion is the main reason I was looking at Angular.

Thank you.


If you keep it client-side: you turn the server-side data into json, then pass that to the renderComponent function (in a script tag or whatnot). Inside your component, you'd use this data in the getInitialState function to set the state of this component (which could pretty much be the whole page).

Does that answer your question?


I assume you just render a big json from the serverside and let the react component to consume it in getinitialstate() of the root component?


Yes. Instead of passing the instance variables from the controller to the view, you instead send it to the client as JSON and basically replace the state of the relevant component(s) (through the ajax callback, or whatever method you prefer).

As your app grows, it might become inefficient to send down the now-huge JSON object, and you might want to add some client-side logic to deal with that. However, this might not even be necessary, as 1) even though you replace the entire state, React will only update what changed, and 2) by using optimistic updating on the client (or whatever the proper term is), the user might not notice that the actual data-syncing is a bit slower. Plus, it'll still be faster than a server-side-only approach.

The nice thing is that sending the total state (of the page or component) every time significantly simplifies matters, to the point where you might be able to keep relying on your server-side framework for most of the logic, at least until you need to start optimizing stuff.


I was thinking along those lines as well, thanks for the reply.


Angular solves more than the UI problem,React on its own doesnt solve the architecturing problem , AngularJS does.

The big weakness of Angular is server side rendering,which involves heavy solutions like phantomjs,while you can render react components on the server.

Angular is not very good at rendering/managing svg either,that's a fact.

I would argue maintaining pure html templates is not that hard.

But frankly Angular solves so many problems these are minor issues.Writing complex lob applications is so easy with Angular I wouldnt want to use anything else.

The only case i'd switch back to backbone+react/vue/ractive and jquery is when i'm writing interactive experiences that are not CRUD apps.

So no,dont switch to React for the sake of switching especially since AngularJS just works. I mean people dont even bother learning javascript,they learn AngularJS ...


Flux is Facebook's architecture for using React in a larger scheme. http://facebook.github.io/react/blog/2014/05/06/flux.htm

It has been discussed on HN before : https://news.ycombinator.com/item?id=7719957

Some good comments there, worth checking out. Personally, I think the message loop architecture proved very good in Windows when processors were slow and had only 1 core and it is at least worth giving it a try in web development.


> Angular solves more than the UI problem

Hence my question. I feel like for some apps I don't need 60% of what Angular has to offer (routing, controllers, modules etc.) I would be satisfied with just directives. Which are probably the part of Angular I like the least.

For SPAs I see no other alternative to Angular currently. In instances where I need heavy JS only on some pages, I'm not sure.


React with a simple router and perhaps some help with your models (Flux or Backbone) might be enough for your needs. Any user behavior that requires new data could be an ajax call that passes back the entire state of the current 'page', which could then replace the state of top-level component (since you want most of your state to reside there anyways). React takes over from there. You'd be relying mostly on your server-side framework for the logic.

You could then incrementally add logic client-side to improve performance, if that's necessary (if the state object becomes too large, for example).


I'd be interested to know what problems Angular has with SVG. I'm currently working on a fairly large SPA and am using SVG fairly extensively, both for simple stuff like icons and for more complicated things like document annotation. I haven't run into any problems thus far.


doing something like

    <my-svg-shape my-directive-that-mutate-svg-props />
doesnt work that well. Displaying SVG has never been a problem,they are like images. Unlike images they can be nested ,animated,modified at run time,scaled... if you think you can just create meta svg shapes with directives think again.


I'm very interested in working with SVG in the browser and have found it to work pretty well with React. I built a demo (Code: https://github.com/jonase/elements, App: http://jonase.github.io/elements/) using one of the (increasing number of) React wrappers for ClojureScript (Chrome only for the moment I'm afraid)


Yes.


Curious if anyone has experimented with Go+React - specifically rendering on the server side as well. Similar to Rails / react_ujs (react-rails gem), seems like you would need to provide Go with access to a v8 runtime and a FuncMap helper in the template to call for the necessary component (JSX -> markup). I've really enjoyed React and I've enjoyed Go in my spare time, but I still find myself using npm for a lot of the, um, grunt work.


I think this post is missing something in its description of Web Components: the fundamental difference between a JS-based framework like React and a Web Components-based framework like Polymer is that the former takes JS objects as primitives and the DOM as an implementation artifact, while the latter takes the DOM as a primitive and JS as an implementation artifact. You cannot wrap your head around Web Components and give both it and JS frameworks a fair shake until you can make this mental shift in perspective fluently.

The line in the post where "You can't even do something as basic as that with Web Components.":

  var MyToolbar = require('shared-components/toolbar');
In fact has a direct analogue with HTML imports:

  <link rel="import" href="shared-components/toolbar.html">
And that's key to understanding Web Components. The idea of the standard is that you can now define your own custom HTML elements, and those elements function exactly like the DOM elements that are built into the browser. This is a key strategic point: they function exactly like the DOM elements that are built into the browser because Google/Mozilla/Opera/et al hope to build the popular ones into the browser eventually, just like we've gotten <input type=date> and <details>/<summary> based on common web usage patterns.

A number of the other code samples in the article also have direct analogues in Polymer as well. For example, the App/Toolbar example halfway down the page would be this:

  <polymer-element name="Toolbar" attributes="number">
    <template>
      <div>
        <button value="increment" on-click="{{increment}}">
        <button value="decrement" on-click="{{decrement}}">
      </div>
    </template>
    <script>
      Polymer('toolbar', {
        number: 0,
        increment: function() { this.number++; }
        decrement: function() { this.number--; }
      });
    </script>
  </polymer-element>

  <polymer-element name="App">
    <template>
      <div>
        <span>{{toolbar.number}}</span>
        <Toolbar number=0 id="toolbar"></Toolbar>
      </div>
    </template>
    <script>
      Polymer('App', {
        created: function() {
          this.toolbar = this.$.toolbar;
        }
      });
    </script>
  </polymer-element>
You can decide for yourself whether you like that or you like the Bloop example more - my point with this post is to educate, not evangelize - but the key point is that you can define your own tags and elements just like regular DOM elements, give them behavior with Javascript, make them "smart" through data-binding so you don't have to manually wire up handlers, and then compose them like you would compose a manual HTML fragment.


The problem is that it doesn't scale complexity-wise. You miss a key point with imports: A `<link>` imports something into the global scope. There's always one global scope. In my example, I was able to rename Toolbar into MyToolbar and use it in my scope. You lose so much using the DOM as primitive and JS as artifact.

And the second you start doing conditional elements (like the tabbed example), Web Components gets pretty complex. In React, it's just `if(shown) { renderItem(); }`.

If you make HTML smart enough, sure, you don't have to manually wire up anything. But then you're left with `x-if`, `x-ajax`, and so on tags. Why not just use JavaScript?


Using JavaScript is fine for things that need script, but ultimately, if I'm building HTML, I'd rather do it in HTML. Put another way: HTML is a great DSL for creating HTML.

As for scoping of imports, you do have a point there in theory, but in dealing with quite a few complex Polymer applications at this point I haven't seen that be an issue in practice. The scoping issue is well known among the people working on Web Components, and AFIAK there are plans to address it.

I'm not sure why you think conditionals are complex in templates. Your example might look like this in a Polymer template:

  <template if="{{ shown }}>
    <my-item></my-item>
  </template>
Yes, there's some token overhead, but in the context of a larger template it pays off to have the entire HTML specified in one place, and in a way that mirrors it's output structure, not spread out over often hard to follow imperative code.

However, as you point out, Web Components doesn't prescribe how to manipulate the DOM, so if you still prefer to do it in script, go ahead!

The point is to produce an element where the browser, developer tools, and your users don't have to care what choice you made.


HTML is a great DSL for creating static HTML.

When you start to bolt on features for dynamism in HTML you end up with Angular. The reason that it has all of those complex features is because it needs them to build real world apps. I'm sure once people have built more stuff with Polymer you'll start to see similar "feature creep".


I've worked with a number of very complex Polymer applications, probably the most complex Polymer applications in existence right now, and the template features have been sufficient so far, and there's always the fallback to code if necessary.

I can think of very few common feature requests (mostly on Shadow DOM, actually), and they don't being to approach the complexity of Angular, which concerns itself with so much more than templating. Angular's complexity is not simply an unavoidable consequence of being used for real world apps - it's just complex.


In practice you'd be namespacing your tags, so it'd be things like <polymer-ajax>, <google-slider>, <facebook-like-button>, etc. At scale you want this, as reading the code becomes quite confusing when you rename each component to your own custom name. It does make typing them out quite a pain (as anyone who's worked with YUI or Google Closure can attest), but that's the price you pay for large-scale development.


We reinvent C-style prefixes-as-fake-namespaces in HTML tag names when we have a perfectly good Turing-complete language with actual scoping rules sitting right here?


I don't mean to evangelize Polymer here - I don't actually have a horse in this race, having recently left Google and being still undecided about which technology my startup will be based upon. I think that the prefixes-as-fake-namespaces approach sucks, but of all the things you can get wrong with your web framework, it sucks a lot less than many other things framework authors do. And it enables the abstraction of "Treat web components like any other HTML tag, except you get to define their object model", which is a really powerful concept, particularly when you consider the possibilities of building the most popular of them into the browser. The problem with all existing JS libraries so far is that they become obsolete as browser technology advances; Web Components is the first one where the components may become the browser technology advances.

To complete your C analogy - yes, C sucks a lot, and it's woefully incomplete in areas like namespacing and packaging. But people still use C, because if you want to do something native it's basically the only choice, and you know that it will interoperate with basically every other language out there. And those people have managed to build some pretty impressive things with C, warts and all, even though a lot of its design choices "will never work" when programming at scale.


There's a really good chance that we'll get scoping for element registration at some point, given that the shadow trees are natural scoping boundaries.


In Ember, for instance, it's perfectly easy for a "computed property" on a View object to return the value of an attribute on a DOM node. In this model, the DOM is the "canonical" representation of state (also fulfilling HATEOAS if "real REST" is your thing). This is a perfectly fine way of doing things, and is possible in Ember or React or any of the above frameworks as far as I'm aware. How the binding between javascript and DOM is registered is entirely up to the library developer.

In my ideal world, I want the performance of the Virtual DOM / rAF batching described in the blog post, I want web components as the underlying DOM / markup that represents my views, and I want to wrap them with Ember-like computed properties and routing structures. But hey, while we're asking for everything, I'd also like universal flexbox implementation, Clojure-to-asm.js compilers, ES6 generators to finally come out...


I think you'll be happy with the stuff I've been working on. Should have something to show off in the coming weeks :)


> The line in the post where "You can't even do something as basic as that with Web Components."

Actually that's factually inaccurate. You certainly can do that. registerElement returns a Constructor function, so you can export that in your module if you want to be able to require it elsewhere.


It's also not either-or. If you have components written in Polymer that you want to reuse, in principle, a React-like framework could render them. (I don't know how well this works today.)


Thank you very much for making the point I was about to.

I was very confused about the Web Components criticism, it seemed like the author didn't understand Web Components at all. My first thought was, "Why would you want to import your element into JavaScript, unless you're going to be doings something scripty with it?"

What you really want to do in a custom elements world, is embrace HTML, as opposed to JS, as the place to build your DOM. Instead of:

    Bloop.renderComponent(Box(), document.body);
do:

    <bloop-box></bloop-box>
Then I don't get this paragraph at all:

  > Aren't you tired of having to query the DOM tree and manually manage the structure do 
  > create UIs? Web Components doesn't solve this at all, it just tries to encapsulate the
  > work. The problem is that building apps is building components, so you inevitably are
  > forced back into the manual DOM management to create your app-specific components (like 
  > how you constantly have to create directives in Angular). You also need to jump into 
  > JavaScript to configure and wire up any Web Components you used. It's a very messy 
  > abstraction, and fools you into desiring a pure HTML-based declarative way to write 
  > apps, which like wanting steak but eating liver.
What?

Of course the point of Web Components is to encapsulate the implementation DOM and the work of manipulating that DOM, and not prescribe how it's done, because you can do it in many ways: manually use DOM APIs, use templating like in Polymer, or even use React if you want.

The author then mixes criticisms of Angular with Web Components. Angular doesn't produce Web Components, has far too many complex concepts IMO (like the $scope.$apply example), and so far has rejected a Web Components centric approach (see their 2.0 design docs). You have to create many directives in Angular because it doesn't support standard 2-way data binding to properties out of the box: without directives you can only bind to attributes. Polymer, for instance, doesn't have those problems, and very complex widgets are built with templates.

And the complaint about needing JavaScript to configure Web Components seems to be completely without merit. Web Components imported with HTML imports are fully capable of registering themselves, so the import is all you need. Yes there's some JS under the hood, but you don't see it, and all of "Bloop" is JS anyway, so I'm really lost on this point.

React may be great, but the future is exactly in encapsulating away the work of building custom elements so that an application can be built of elements sourced from different vendors using whatever tools they want to implement them. I would have no problem using custom elements built with React, but at this point I am not interested in components that force me to use a particular framework. Trying to proclaim that all apps should be built with this or that awesome framework, is a quickly aging point of view.


According to the Web Component spec a custom element must contain a dash. Also the convention is to use lowercase. http://w3c.github.io/webcomponents/spec/custom/#concepts


I know, but I wanted to make the correspondence between the examples as clear as possible, including using the same names. In practice it'd be something like <my-toolbar> and <my-app>. (Well, in practice it'd be something like <polymer-toolbar> and <companyfoo-app>, but hopefully people get the point.)


Just want to say thanks to jlongster and everyone who's commented on here; I created an account just to say thanks. I'm an amateur web dev/designer trying to figure out how to move beyond static web pages, and have read what would probably amount to a literal ton of material were it printed out, on frameworks, libraries, and more acronyms than I could imagine. Outside of HTML, JS, and CSS, even "basic" things like Sass and CoffeeScript I hadn't heard of just a few months ago, and I've since been all over the world (wide web) looking for info on ASP.NET (which my group at work decided last year was what we should be doing "web-kinda stuff" in, as well as Angular, Ember, Backbone, Knockout, Node, etc etc, and everything new (to me) that research like that comes with.

The discussion here has led me to a few more things to research, but I feel it's been very helpful in helping me think critically about the vast array of possibilities a budding web designer has to deal with. I just wanted somebody to provide an objective view of "If you're going to be doing medium-complexity web apps end-to-end, then learn ______" and I still would love that, but don't think it's possible to get. The alternative, as I've been doing, is just to learn a little about everything, try to figure out the kind of things I plan to do, and then find the paradigm that works, be it vanilla technologies, something like React, Web Components, or a framework (and I've been trying to learn Angular and like it, but it's tough to grasp). It just seems like as soon as I've decided on what I want to learn, I read a new post with a title like "Why You Shouldn't Use <whatever I just decided to learn> and Why <something new I've never heard of> Is Really the Way to Go."

So anyways, a long-winded thanks, but a thank you nevertheless for the open discussion here; I feel better now that I'm not trying to find the one-and-done "best" thing for making web apps in general.


For those who are only interested in the render loop, I made a library[1] around this abstraction.

I plan to expand it with a toolkit to allow thinking in terms of batches, queues and consumers, à la bacon.js[2].

[1]: https://github.com/zenoamaro/honeyloops [2]: https://github.com/baconjs/bacon.js


Leo Horie, author of Mithril, has written a blog post where he explains how to re-implement some of the article's examples using Mithril (React-like client-side Javascript MVC framework): http://lhorie.github.io/mithril-blog/an-exercise-in-awesomen...



I like the state and property features of React, but I still don't understand why more people aren't using Chaplin instead. Because quite honestly, the syntax of every other framework - React, Ember, and especially Angular - is complete gobbledygook by comparison.

Example: in Chaplin, components are views or subviews (because it's still an MVC framework, which is another discussion for another time). The views by default render automatically without you having to call anything. But if you did, you'd write @render() (because hey, Coffeescript saves keystrokes and sanity). That automatically renders the component in the place you've already specified as its container attribute, or if you haven't it renders to the body by default.

Whereas in React, you have to write this garbage: Bloop.renderComponent(Box(), document.body);

WHY. Can't we write a framework that intuits some of this crap? Shouldn't we use a framework that reduces the time we spend writing code?


Automatic rendering is fine in small projects. Seemingly random appearance of widgets would, however, drive the debugging person crazy.

Comparing this.render to Bloop.renderComponent is superficial. If rendering needs to have a handle on different resources, you'd either violate the encapsulation in the former example, or write a service to couple them on a separate layer -- that service might as well be called Bloop.

Some of this crap makes hard things possible.


I've been a longtime user of Chaplin and I love it, particularly when it comes to the Composer and Dispatcher. I've been experimenting recently with killing the view layer completely in favor of React templates, since I think react does a better job of managing view state, but doesn't include the rest of the stuff I need for my app like routing and data management.


If school books had online versions like this page, it would make reading so much more fun.

Great read, by the way.


I was at a meetup where the speaker suggested react is great for business-like apps, but for things with an insane amount of dom objects like html games, it tends to get bogged down.

Since React claims to be super fact, has done a performance comparison to see in what situations and how much better react performs in certain cases, compared to say, angular.js or more vanilla frameworks?

(Also I hear that there is a really great speedup that using OM gives you, but I haven't seen any comparisons with om either)


if you are going to update the DOM 60 times per second no databinding/reactive whatever framework makes sense.

there is so much overhead with these solutions performances would just be bad.

However it would be interesting to extract the virtual DOM from React to use it in the context DOM based games, being able to mark elements as dirty in order to redraw them is a usefull feature.One just doesnt need all the JSX/databinindg stuff for a game driven by a gameloop.


JSX is a build step and is completely optional. If by "databinding stuff" you mean React's setState and friends, almost all of React's code deals with the actual diffing and browser handling. Components are not much more than functions from props to a virtual DOM output. It's easy to use React without ever calling React.createClass (just pass the output of React.DOM to renderComponent). Still, we're looking at separating these parts of React so that you don't have to pay the file bytes but it's not a very significant difference right now anyway.


thanks for the info, i'll try to hack something with React for my next DOM based game and see if it works.


Check out this example of a 3D game using React: http://facebook.github.io/react/blog/2013/08/26/community-ro...

(Wolfenstein Rendering Engine Ported to React)


I recently watched a presentation about React's approach (I think from a recent JSConf) and it sold me, at least enough to try. The approach makes total sense to me, and I agree with many of its criticisms of Angular in particular. I really loved the reconsidering of our idea of "separation of concerns", that if we reconsider the scope of the concern, we can devise an approach where templating and logic go together. I'm excited by these ideas.


Seems like putting templates inside js is a step backwards. The advantage is that you can package templates together with js? That problem is still solvable while maintaining separation. For instaces with browserify tramsforms you can just require( 'my-template' ).

https://github.com/epeli/node-hbsfy https://github.com/rotundasoftware/nunjucksify


Tester: The UI is wrong right here...

Developer: Hmm...I wonder how long it's going to take me to figure out where that HTML was generated in my javascript.


Did you see this tool ? I find it quite helpful for debugging JSX and finding the root of the problem.

http://facebook.github.io/react/blog/2014/01/02/react-chrome...


I think tools like React actually make debugging situations like this easier. Instead of trying to figure out what actions a user took that manipulated the DOM with jQuery n times, I can take an exact snapshot of the state of the application and walk through how it is being rendered.


Developer: use React.js. Events go one way only, no funky feedback loops between views, models and controllers.


You hit the nail on the head why these things are bad.

You can either build something on a mass production line, where you're just screwing the same bolt in day in and day out, or become a master craftsman and build it with proper care, design, and quality.

These frameworks are nothing more than a factory floor and if all you do is build apps with a framework you're little more than a paid glue stick piecing bits of code together. Or you can become a master software developer and build something of quality without needing a crutch like a framework.

Now, if the needs of the project are such that a framework will suffice then by all means, use a framework. Chances are, if you're doing more than building a working prototype then at some point a framework is going to fail you. If you enjoy building apps using frameworks then by all means, do it. But to my mind you're doing your customer a disservice.

Contrast that with great software developers (and I've been fortunate to have worked with some really great developers) who abhor these frameworks. They can get more done with less code and ultimately deliver the project faster without frameworks. The tradeoff is that it takes time and dedication to achieve that level of mastery. I personally would prefer that path.


I never quite understand arguments like yours. As aquark pointed out, it's 'frameworks all the way down' anyways. Unless you're a one-of-a-kind master, you're always relying on multiple levels of abstraction.

I don't know who pointed it out, but I find that a good rule of thumb is to master at least one layer of abstraction below the 'current' one. So in the case of React, you'd first make sure you are proficient with javascript, the DOM, and how the web works.

If your point is to underline that using frameworks without understanding them is a bad thing, I fully agree. But arguing that 'these things' (frameworks) are bad just seems silly.

Clearly some clever people at Facebook found it useful to abstract certain things in a certain way, and many other people (some clever) like their approach. They've actively considered IanDrake's problem (in fact, they talk about this in their talk on React), and felt that their solution was good.

If I can build a performant client-side-heavy web-app in half the time because of React, I'm doing the client a service, not a disservice.


Here's my experience with frameworks:

They're really good at getting you to 80% completion really fast. The next 10% takes a little work but its doable. But that last 10%... its like pulling teeth. With tweezers. Covered in grease.

That last 10% is the thing you need done to successfully deliver the project but which the framework designers didn't consider.

In my experience you always run into that last 10%. The net result is that all those speed gains you realized early on are completely lost (and then some) because you're fighting with the framework.

So sure, understanding the framework might help you with that last 10%. But I personally think you're better served mastering JS, the DOM, and how the web works. Which really isn't that hard by the way!

And anyway, if frameworks were so great why are there so many? It seems like a new framework gets announced every week here on HN. The shear tonnage of frameworks alone makes me question their value[1].

Now if none of that can convince you, consider this; the company I work for got rid of all their framework programmers and replaced them with me and a couple other software developers who have experience building products without using frameworks. And they pay us more money than they paid the framework programmers. Why? Because we did more work with better quality in the first six months than those other guys could do in 2 years of gluing framework code together. That last 10% hit them HARD and cost them their damn jobs!

1: I do recognize that frameworks provide value. My argument is that they are way overused. Great for building working or semi-working prototypes in order to test an idea in the market. Terrible for building anything that needs to be continuously maintained.


So if i may ask, what do you use?

Just raw DOM manipulations?

I feel like your argument is partially valid, but your argument also sounds like it effectively argues for pure Assembly. Anything ontop of that costs you a ton at the 10% mark. Now, i understand there's a difference between a Framework and a Language, but i hope you can understand my point.

I feel like you're going to one extreme, and arguing against another. Arguing opinionated frameworks with equal opinionated design seems odd to me.

Lastly, what are your thoughts on code maintenance? I feel like there is something to be said for "Get it done" thinking and "Make it maintainable", and sometimes they don't see eye-to-eye.

If it's cleanly written, with a framework that makes sense, isn't it far easier to maintain than raw JS? (Not specifically about React, just in general)

Disclaimer: I like React quite a bit. But i don't think you're "wrong", we just see things differently.


I prefer libraries. I'm partial to jQuery[1] for DOM manipulation, simple effects, and AJAX. I love Underscore. Both libraries allow me to pick and choose which parts of them I can use without imposing on me to do it The $FrameworkName Way. That said, when I can use pure JS I do.

    Lastly, what are your thoughts on code maintenance? I feel like there is something to be said for "Get it done" thinking and "Make it maintainable", and sometimes they don't see eye-to-eye.
You're right, they don't always see eye-to-eye. Frameworks are handy if you need to "get it done". You also need to educate your customer that you will have to make trade-offs and cut corners when trying to just "get it done". But I also argue that with enough experience you can, in fact, get it done and make it maintainable. I've seen that time and again.

The reason I don't believe you can write something cleanly with a framework and it be easier to maintain is that the framework is a black box of unknowns. So one option, as someone else has mentioned, is to try to fully understand that black box. But then you've just tied yourself to that framework. Wouldn't you be better served mastering the technology that the framework is written in?

1: jQuery proper. jQueryUI isn't too bad but is still a little more black box than I prefer. I really dislike jQuery Mobile for all the reasons I dislike frameworks.


The biggest problem I've found is that while theoretically frameworks should be easier to maintain (and if used right, they might be), in practice using frameworks are an excuse for developers to do something quickly, The <Framework> Way be damned.

The result of all this is code that is harder to maintain, even for those who know how to use said framework.

While I'm not against frameworks myself (in fact I argued in favor of them in this very conversation), I have become much more weary of them. In fact, after a brief affair with CoffeeScript I've even come to be more hesitant about using that or other 'transpilers', as I recently ran into the problem where I had to revert to plain js and I discovered that I'd lost some proficiency.

That said, it depends partly on the developers, and partly on the amount of structure the framework forces you into.

And that said, I suspect using a framework often serves more to alleviate managers' concern about maintainability than anything else.

There's one case where I would strongly suggest someone use a framework though, especially an opinionated one such as Rails. By following the Rails Tutorial by Michael Hartl, I learned a lot about best practices that I wouldn't have learned had I cobbled together a bunch of libraries. So for beginning developers, a framework might help them get started with their prototypes and whatnot.

Then again, maybe that worked for me because I can't help but want to look behind the curtain... I've certainly met my share of developers who never seen to wonder what's behind the magic.


Thanks for the additional insight, appreciated :)


The trouble is that many devs can't see past that 80% to see the 20% that's left. They whip up a little app at night, it works really nicely and they assume this means the app they're working on during the day should be "rewritten" in the framework-du-jour. Then they hit that 20% "wall", blame the framework as "lame" and start hunting for an alternative. Rinse and repeat.

Last year I got excited about NodeJS and started working with it quite heavily. Then I started to see holes - difficult debugging, so-so tooling for development, mixed bag of JS components, and so on. I then stepped back and realized that although it was interesting, and I can see it useful for some specialized server-side development, I don't see it as compellingly different than current alternatives (Rails, .NET, PHP, etc) to try to build a whole web app with it.

To extend your argument, I would state that frameworks are only about speeding up the initial creation of an application that fits into a narrow set of assumptions. Frameworks, by their very nature, capture a set of decisions by their designers about how an app should work (or behave). As long as your app fits nicely into this box and you can live with the downstream risk that maybe it won't one day, then go for it.


I agree with the clarification that there are differences between Rails, .NET, PHP, and NodeJS. Rails & .NET are frameworks (strictly speaking, .NET is an amalgamation of frameworks and languages). PHP and NodeJS are languages.


Put that way, I fully agree. If I were to hire programmers for my company, I'd rather have a few like yourself than a bunch of Rails devs that don't really know Ruby nor Rails' internals (for example). And I've worked at a bunch of places where the effects of using frameworks without fully understanding them were readily apparent.

I took issue mostly with the blanket statement that frameworks are bad, because I think there's a lot of variety. Backbone, for example, is so basic that it might be useful for 'master' programmers, whereas Rails is a monster framework that is a bitch to handle if you get to that 10%. And I'd argue React, which is more of a library, could be a very useful abstraction that leaves you free to do things your own way, or even replace it eventually. But I might be wrong about that! I'm not a master...

Also, I guess in the context of the framework/library-explosion it makes sense that you'd point out the problems with a little less nuance :). And it's a good reminder for me as a young framework-raised, self-taught whipper-snapper to make sure I become a master at my 'craft'.

And not just because it pays better.


That's a terrible argument my dude. Do me a solid, what do ya'lls variable names look like right now? Or just real quick, LOC on the smallest file you got.


What kind of useful metric could variable names and lines of code possibly provide?


Frameworks decrease LOC, which drastically improve readability. Any shorthand variables decrease readability. Frameworks are great at enforcing these rules.

If your average LOC is ever more than 200 lines or so, you've got a messy app.


React is a paradigm with only one existing implementation.

Ranting against frameworks represented by React is a strawman here. It doesn't include a router, nor a model layer, nor the traditional controller. It's a miracle that it's even compared to Angular and Ember, but I guess that's the extent of the power of View + solid declarative nature, so we'll take it as a compliment.

We also don't want to turn it into a huge framework, so if that's your only concern here, then please feel free to give it a try =).


Of course it really is frameworks all the way down. Unless maybe you're building systems by laying out your own transitors.

The trick is to understand the strengths and weaknesses of any given framework and match those with the constraints of your project.


I disagree that its frameworks all the way down. There is a distinction between frameworks and libraries. React, Angular, et al are frameworks in the truest sense of the word.

Things like jQuery and Underscore on down to stdio.h are libraries. You can pick and choose from what they contain but they're not so tightly coupled that they get in your way.

They're a tool belt with tools that do one thing and do it really well. Frameworks are like having a tool belt with a hammer that also has a saw on the end but in order to use the saw you have to grab the screwdriver even if you're not actually using it.


I would argue that React is closer to a library than a framework. It's a small library with some useful functions for making web components. It helps by removing a bunch of boilerplate code that you would have to re-write with each new app. The thing that it doesn't do is hold you hand and tell you exactly the way things should be done as some of the other frameworks do.


Thanks for pointing out the distinction. I forget about that sometimes.

That said, React is a "A Javascript Library for Building User Interfaces." And to me me it does feel more like a library than a framework.


React is a library, plain and simple. It has literally no opinions on even basic stuff like routing, or how to manage application data.

It takes your data as an input and by some mechanism lays out a visual representation of it defined by your components render methods, being sure to update the visual representation as the data changes. The rest are implementation details.


I'm curious which part of React you consider the hammer and which part you consider the screwdriver.


The thing is, for the web you should not need frameworks at all. A couple of libs maybe, but what we are seeing now is getting ridiculous.


Your comment implies that you recommend web apps never do any DOM generation or manipulation using JavaScript, and are instead purely static HTML documents. For that matter, your argument would logically extend to opposing backend HTML generation as well, like Rails templates.


>you recommend web apps never do any DOM generation

Full stop right there and you're correct. I really prefer to limit code that looks like:

     element.innerHTML = '<div>Do you really like content in your JS like this?<div>';
I'd rather have the HTML loaded as one file and have the javascript in another acting on that HTML. Right now my favorite library to use for this is Knockoutjs.


Knockout has HTML-esque template too, not unlike Ember or even React.


It was really cool, until I realized that scrolling broke the back button.

I thought one of the cardinal sins of web design was don't break the back button.


Has anyone tried to use a different template engine with React? I was just wondering, since I didn't want to use JSX inline, and writing out html with React.DOM isn't appealing either.

I just wanted a way to put templates in <script> tags that get loaded by React Components. That way, I won't be mixing templates and the behavior of the components. Has anyone done this before?


There's this: https://github.com/mereskin/jsxify

But really, once you get used to keeping everything together it really does feel better. You just have to try it out.

Personally, since I use CoffeeScript, I like this lib:

https://github.com/atom/reactionary

which, since it strips out the required `null` or `{}` first parameter, feels very much like haml or jade.


I use coffeescript too, so I should be able to use reactionary to write the dom helpers it exposes in my JSX. So then the coffeescript -> jsx on server side, then jsx -> javascript browser side, is how it works, right?

I think I'm slowly being convinced putting it together in the same file makes sense, since it's a single component, and the what's being displayed is coupled with what you'd do with it, so I guess it should belong in the same place?


Well, the way you should do it is abandon .jsx completely, and just stick to .coffee.

Something like this:

React.createClass

   render: ->
 
      {div, h1, span} = require 'reactionary'

      div class: 'home',

          h1 "Hows it going!"
Clean and simple, particularly with CoffeeScripts default return.

As far as templates go -- and this is what I always tell people -- structure your code in a clean way which makes the render function pop out and you might as well be working with a separate file! It really does make more sense after a while.


Cool, I'll give it a shot.

I checked out reactionary, why couldn't I just do:

{div, h1, span} = React.DOM?


There are some conference videos of Peter Hunt where he talks about why this isn't a good idea.

- Placing markup and logic in separate places separates languages, not concerns

- React/JSX has the full power of JavaScript, not some intentionally crippled lookalike


The awkward right panel that changed abruptly from time to time, especially the first transition, made me skip the content.

Using a non-common ui idiom is risky. The presentation and topic don't match in a way that reader (i.e. me) had enough expectations left when it comes to what you might actually have to say.


I feel kinda bad that you're being downvoted. I also felt the presentation was a little jarring. The right panel seemed to change at strange times related to the content I was reading. Perhaps it was an overuse of the "change things while the user is scrolling to make it seem cool" theme I've been seeing a lot.

On the other hand, I actually found the content pretty great, but I'm not a web developer so take that with a grain of salt...


Instead of having React altogether, wouldn't it make sense to have the browser keep track of a virtual DOM, and only repaint whatever changes on its own, while managing its own requestAnimationFrame and paint cycles?

P.S. I haven't looked into this in depth, just throwing an idea out there.


I may be mistaken here, but I think that the main advantage of the virtual DOM is to avoid calling across the JavaScript-native boundary. Since calling browser APIs is inherently expensive, the virtual DOM improves performance by reducing the number of calls to these APIs and/or batching them together.

Similar techniques have been used in other types of programs where performance is critical - for instance, user mode networking and user-mode thread scheduling can be quicker than the kernel-mode equivalent because it reduces or eliminates expensive system calls.


Yeah if the technology was in the browser that would possible.

From what I understand, the core idea is that changes are applied to the virtual DOM in a very simple way (from the application point of view). Then there is another piece of code that knows how to efficiently find the diff between the vDOM and DOM and apply the changes. It seems that last part could be done by the browser.


The additional layer of redirection, at least conceptually enables the use of application specific, or pluggable, vDOMs and/or diffing strategies.


So I'm curious how one would implement something like drag and drop in a React app?

Would you model the drag in the main data model somehow? Or would you do that all externally (with traditional DOM manipulation) and then update the model when the drag is complete?


The latter. You would use html5's draggable, then update on complete.

Check out http://webcloud.se/sortable-list-component-react-js/


I wouldn't use the DOM. To "embrace" React you really need to forgot the real DOM exists and instead track the drag in the components state and handle moving the items around in the render function.


Needs a catchy buzzword. So, can we all agree to name this ... NoHTML?


This is definitely a "Sell this to your boss" type of post :) Great work.


I'm honestly really, really wary of minimalistic front-end frameworks after two years of working on single page web apps.

All that ends up happening in practice is untested, messy code with deadlines up your ass and 0 developer ergonomics. Zero.


It's hard to say what, exactly, you're referring to here. React, in many ways, is not so much a framework but rather a really smart template system. It's ergonomics, I've found, are quite nice.


I was half-expecting a gambit Scheme post :)


This is great except the button is broken.


my gripe with those is that you remove UI complexity but shove usability and accessibility over some dark orifice.

All those things are cool for social apps (a.k.a. fart apps) but for business ready platforms this is just silly.

for example, a link that i can middle click or bookmark or send to someone, etc would be much more useful even if not as spiffy as those scrolls


back button behavior is atrocious ....


But Javascript is awesome! Its the future.


Javascript doesn't inherently break the back button. Sloppy developers do.


Certainly, but sloppy developers using Javascript makes it way easier to break the back button than server-side rendering.


You can break the living hell out of the back button with server-centric solutions (hello asp.net, and POST's for everything)


Fair point. I feel like us server folk have figured that part out by now at least, the Javascript stuff is still quite the wild west on the client.


I hate OP website, why i got to click the back button 10 times to comeback here?


Damn, Javascript is only becoming messier. I think I'll just watch it from the distance and wait until someone figures out the best way to deal with it.


That might take a few browser generations sadly. HTML6 anyone?

edit: HTML/next apparently: http://www.w3.org/wiki/HTML/next




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

Search: