10 ms·
The Case for React.js and ClojureScript
- mantrax5 12y agoJust the slides aren't enough to sell me here, I'm sure the missing video to go with this fills in the holes. Buuut. "Problem - UI is complex - because DOM not Reactive - what if it was reactive - random code sample", is just non-sequitur out of context. DOM programming is inherently "reactive" - it's event based. Furthermore, I think it's nice that tools like React.JS exist that "free the developer from manually programming the DOM", but that's exactly what Angular.JS offered too. Automatic binding and updating yada yada. Why is this author flaming Angular.JS? Was it because its leaky abstraction turned out ugly over time? Well the same fate is awaiting React.JS and its "minimally leaky abstraction". Leaky abstractions never remain "minimally leaky" over time. The fact they're leaky from the very start shows the model was flawed to begin with. Angular.JS does manual compare between two large model objects to detect changes and emit model update events. React.JS does manual compare between virtual DOM and real DOM and emits DOM update events. They both try to solve the hardship of having to update your DOM, via an abstraction that only works well in specific circumstances and incurs irreducible runtime overhead when behind the scenes structures have to be compared over and over and emit update/change events. Sometimes the problem is in the platform. But even more often a bad developer blames the platform for their own inability to architect their app cleanly and thinks leaky abstractions are the answer.
- peterhunt 12y agoThe reason UI programming isn't reactive is because reactive systems are immediate mode (describe the whole state at any point in time) and the Dom (hell, most UI toolkits) is retained mode (stateful). So you need to abstract that away somehow and that abstraction is guaranteed to be leaky to some degree. The thing that separates react from the rest (disclaimer: I work on react) is that these leaks are pushed to the edge of your system (that is, you need an external signal to re render) rather than threaded throughout your system (like requiring everything to go through $scope for one). We have seen massive dev efficiency gains because this removes many limitations for not much downside.
- mantrax5 12y agoHello, Peter. Incidentally I was just watching one of your presentations on YouTube to understand the reasons behind React's design choices. The thing I still can't understand is why we need to model the UI around emulation of immediate mode. Two big reasons: 1. The fact is when you want to create a meaningful animation between one state and another, you need to be aware and in control (as a developer) of what exactly the change is. Diffing may produce one possible valid state change delta for the developer to work with, but no guarantee it'll be the correct one. So what does that mean for animated transitions? Is immediate mode dooming them to either not be used, or to be semi-arbitrary depending on what the diff engine decides? 2. Fact is that the browser usually has no access to the full server-backed state of the widget that it's rendering. Instead, the communication with the backend that powers said widget (say a chat box) is in the form of delta state changes. You don't get the full chat log from the server every time someone sends you a chat message, you get the change only: new message from x. So if we need to be "state aware" and communicate with "state change events" so to speak with the server anyway, why suddenly drop that knowledge and pretend all the state is local by emulating immediate mode rendering? It doesn't feel like less work. It feels like more work, and less possibilities (said animations in point 1).
- peterhunt 12y agoThumbing this from my phone so can't go into as much depth as normal. 1. The diff algorithm is deterministic and accepts that some widgets are stateful. You can tell the system which items to preserve and which ones to destroy by providing an identifier. This is essential complexity in the current world we live in (global dom state tied to element instances like focus). If we were to throw out the Dom spec and rebuild it we would not need to do so much. So you can animate by tweeting a value and rerendering/diffing every frame. Facebook look back video editor works this way. 2. Yes, but delta updates are imperative mutations over time and humans are really bad at keeping track of them so we should try to isolate them as much as possible. We have a separate system that coalesces these deltas into consistent views of the world which are then passed to react. This is also the role of systems like rx. One way to think about it is like rest. People like rest because it is predictable: URL refers to the same resource always and refreshing the page always works consistently and you never need to think about deltas.
- rdtsc 12y ago> Buuut. "Problem - UI is complex - because DOM not Reactive - what if it was reactive - random code sample", is just non-sequitur out of context. How is it a non-sequitur? Random Code sample? Are you being a little too aggressive maybe. > DOM programming is inherently "reactive" - it's event based. I don't think you quite know what reactive means. http://en.wikipedia.org/wiki/Reactive_programming http://en.wikipedia.org/wiki/Reactive_programming Maybe you should look a few things up before jumping in. > Why is this author flaming Angular.JS? If you are a proponent of it and you think you are defending it here, you might actually be doing it a bit of disservice. He made the point that Angular JS is complex and showed a list of new concepts it introduces -- services, directives, etc on top of the already existing ones, controllers and so on. It is a personal opinion. You don't think it is complex, ok, share your opinion, it doesn't mean the author if "flaming" anything. > They both try to solve the hardship of having to update your DOM, via an abstraction that only works well in specific circumstances They both solve a similar problem with some differences. Author thinks one does a better job sometimes. > . But even more often a bad developer blames the platform for their own inability to architect their app cleanly and thinks leaky abstractions are the answer. Are you implying the author is a bad developer? Can you show that. So far you haven't
- deleted 12y ago[deleted]
- danabramov 12y agoCheck out this talk: http://vimeo.com/92687646 http://vimeo.com/92687646 At around 30:00, he talks about why Angular's two-way binding is evil, and why React's approach makes more sense. In short, two-way binding means there is no single “source of truth”. That makes debugging and non-trivial interaction very difficult. React solves this problem by always having one source of truth—component's `props` and `state`.
- mantrax5 12y agoThanks, bookmarked.
- numbsafari 12y agoDecent presentation. Something that would be really helpful for me, as a consumer of these slides, would be to have a better setup between the slides with just code. I get the impression that, with some of those slides, you would be saying something while that slide was up. But without your audio, I have no idea what that is and so the slides are confusing at that point. So, if you are giving a presentation that goes best with audio, it'd be awesome to have the audio. If you are giving a presentation with the goal that it can be consumed without the audio, would it be possible to have your speaker notes show up on the slides where you are showing something and talking? All that said... I'm very interested in looking at react.js. I don't know that it would work with the team that I am working with now, mostly because the team that does the front-end work doesn't do JS programming so much as they format HTML and CSS. Does anyone know of something that mixes react.js with templates? Any success/failures in that regard?
- Skinney 12y agoReact comes with it's own 'template' library called JSX. It allows you to mix React/JS and html. Example: function render() { return <div>Test</div> }
- dustingetz 12y agoI am the lead guy of a React library: https://github.com/wingspan/wingspan-forms https://github.com/wingspan/wingspan-forms All the design work was done by an actual designer who maintained the JSX directly. He knows enough javascript to get around but basically he just pretended it was HTML. JSX is awesome because it means designers can commit directly without involving engineering.
- ryanjshaw 12y agoAs a developer I'm interested enough to try React.js on my next project. However, it seems like designers will still need to write Javascript to implement repeating structures (tables, lists, etc.)? Just like designers don't want me fiddling with their HTML and CSS, I don't want them fiddling with my code -- but React.js's model seems to make such a separation of concerns impossible?
- mossity 12y agoThis seems slightly cribbed from "Rethinking Best Practices" by Pete Hunt https://www.youtube.com/watch?v=x7cQ3mrcKaY https://www.youtube.com/watch?v=x7cQ3mrcKaY
- Confusion 12y agoPete Hunt is quoted on one of the slides, so that sounds likely :)
- the_watcher 12y agoThe simple v. easy section was interesting. Those words are probably used too often as synonyms. In reality, we should think of them differently - something easy is something that a lot of people should be able to replicate without much expertise, whereas something simple, a lot of people should be able to understand (what it does, the purpose, how to use what was built), but not necessarily replicate themselves. I think that is probably the right distinction, although it is a very fine one.
- KingMob 12y agoIf you haven't seen it before, check out Rich Hickey's talk on the topic: http://www.infoq.com/presentations/Simple-Made-Easy http://www.infoq.com/presentations/Simple-Made-Easy
- the_watcher 12y agoThanks! Never had seen it, really interesting.
- deleted 12y ago[deleted]
- haberman 12y ago> Immutable data structures make React's diffing algorithm really smart. I was very intrigued when I heard this claimed in a blog article a while back. So I investigated this claim deeply and was not entirely convinced. For example, the immutable approach to tree diffing actually requires more work in some cases, since you always have to diff from the root. I wrote more about this here: http://blog.reverberate.org/2014/02/on-future-of-javascript-mvc-frameworks.html http://blog.reverberate.org/2014/02/on-future-of-javascript-...
- freshhawk 12y ago"Om is an immutable data structure library" The immutable data structures come from clojurescript, all the default data structures in clojure/clojurescript are immutable. Om is react.js bindings for clojurescript and some state management functionality. You can't blame me for disregarding everything after that mistake can you? It casts quite a bit of doubt on "I investigated this claim deeply".
- haberman 12y agoIf you see any factual inaccuracies in the substance of my conclusions, please let me know (for example, swannodette's updated information in a sibling comment is very useful). I will update my article to correct the distinction you mentioned. > You can't blame me for disregarding everything after that mistake can you? Yes, I think it's unreasonable and uncharitable. Any nontrivial piece of work is going to have mistakes. I was investigating a set of technologies that were totally new to me (React, ClojureScript, Om) and I had no friends who were experts in the subject matter to review the article for me prior to publishing it. Given that, I think I did a pretty good job actually. The mistake you mention has no impact on the article's conclusions. My article was not attacking or argumentative, but a good-faith attempt to understand the prior article's claims better.
- freshhawk 12y agoI also didn't mean that as an attack, disregard was probably the wrong word to use. I meant that since it is indeed a non-trivial piece of work and the performance characteristics in question are very complex and depend quite strongly on the Clojure state model then it's reasonable to assume your conclusions are wrong because of the mistake made at the start of your chain of reasoning. For example: "And it is hard to imagine convenient two-way data binding being built on top of immutable data structures." makes perfect sense if you are working in javascript, but is a normal and elegant way of doing things in clojurescript (and the cursor implementation in Om makes them incredibly convenient).
- coolsunglasses 12y agoI'd rather use a typed language which is why I'm following the development of PureScript ReactJS bindings. http://www.purescript.org/ http://www.purescript.org/ http://tryps.functorial.com/ http://tryps.functorial.com/
- marknutter 12y agofunction renderApplication(tweets) { return(document.dom.ul( { class: 'tweets' }, tweets .sort(compareTweetsByScore) .slice(0, 5) .map(function(tweet) { return(document.dom.li({ class: 'tweet' }, tweet.text); }) )); } What I like best about Ember and Angular.js is that you don't have any hint of the DOM in your controllers. I don't like how the above example mixes concerns.
- antris 12y agoIts concern is mapping the tweets (data) into a view (another form of data). That is one concern. If you like, you can split it into smaller functions (since everything is referentially transparent, unlike in MVC), but that would be overkill considering the given example.
- camus2 12y agothe point i think is scope injection makes controllers clueless about any view responsability. That's a powerfull idea. Well they are not totally clueless because one still needs to "force update the view" sometimes in Angular ($scope.$apply),but this can be avoided by using Angular promise api.
- benaiah 12y agoThis would be considered part of the view, not the controller, and would thus be organized as such. It's also a very small example - a real application would have a number of differences with this.
- danabramov 12y agoPete Hunt talks about this in Rethinking Best Practices video[1]. This is one concern, not two. [1]: http://www.youtube.com/watch?feature=player_embedded&v=x7cQ3mrcKaY http://www.youtube.com/watch?feature=player_embedded&v=x7cQ3...
- baddox 12y agoI think I get it. Can anyone let me know if this description of my understanding is close to correct? React lets us program reactively by rerunning the entire JavaScript description of a component every time its data changes. This lets us use "normal" JavaScript code to describe our component (as opposed to explicitly attaching Ember dependencies or using Angular ng-* attributes). This normal JavaScript code will describe the component at all points in time, not because there is two-way binding, but because any change in the state of the component will cause the entire JavaScript function to re-execute. React's virtual DOM, then, doesn't have anything to do with reactive programming per se. It's just the way that rerunning JavaScript code for every single data change can be made performant.
- danabramov 12y agoThis sounds correct.
- skybrian 12y agoPretty much. It's similar in spirit to reactive programming if you think of a component as exposing a Signal<Virtual DOM> that the renderer subscribes to. Also, the Signal<Virtual DOM> depends on a Signal<Props> and a Signal<State>. And the Signal<Props>, in turn, depends on the component owner's Signal<Virtual DOM>. You also have control over whether the render() method is called by substituting your own diff function (shouldComponentUpdate).
- hcarvalhoalves 12y agoHave you ever programmed graphics? To make a paralell, usually in graphics your main loop reacts to events (user input) and you change some internal state in some object(s). Finally, you get all those objects that know how to render themselves, see what's relevant and render the whole scene. You don't have to care about pixels, you just react to events and blit a representation of the entire state. React.js is the same, the difference being your components "render" themselves to the DOM, and because it's a tree, it's naturally composable. It's still a pipeline taking state and outputing a representation though.
- 12y ago
- civilian 12y agoIs the presentation available anywhere? The slides just don't cut it for some of this.
- programminggeek 12y agoUm, a lot of what I see in React.js reminds me of Knockout.js but without the data binding on the view side. I know there's a lot more to it than that, but the simple example seems like something Knockout's MVVM model could handle in similar or less complexity. So why use React.js when Knockout.js works perfectly fine?
- dustingetz 12y agoMaybe it's easier to see by example. Knockout doesn't do so well when the state isn't trivial. Build these in Knockout, I dare you to try. (Once upon a time, I tried, and failed, and now I use React) http://wingspan.github.io/wingspan-forms/examples/form-twins/ http://wingspan.github.io/wingspan-forms/examples/form-twins... http://wingspan.github.io/wingspan-forms/examples/faceted-search/ http://wingspan.github.io/wingspan-forms/examples/faceted-se...
- Aqwis 12y agoUh, both seem relatively trivial. I've built considerably more advanced stuff in Knockout.
- candl 12y agoThese seem to be React wrappers around KendoUI. There are wrappers in Knockout for the same library as well. http://kendo-labs.github.io/knockout-kendo/index.html http://kendo-labs.github.io/knockout-kendo/index.html Writing custom bindings in Knockout is quite easy. I also do not understand the appeal of React. Performance is often cited because of the virtual DOM implementation, but for example in this benchmark Knockout is three times faster than React in my browser. http://vuejs.org/perf/todomvc-benchmark/ http://vuejs.org/perf/todomvc-benchmark/ The only criticism that can be made against Knockout is the syntax when using observables in bindings (the ugly and error prone parentheses) and lack of reusable components. The first is solvable by using the Knockout-ES5 plugin if we are willing to drop IE6 to IE8 support. As for the second, components are finally comming to Knockout: https://github.com/knockout/knockout/pull/1396 https://github.com/knockout/knockout/pull/1396
- 12y ago
- camus2 12y agoWhy isnt clojurescript compiler written in clojurescript? i cant run java on my machine.
- lgas 12y agoOut of curiosity, why not?
- thinkpad20 12y agoIf it's written in Clojure, couldn't you just self-compile that Clojure into JavaScript? I suppose you might have to make a few changes, but it doesn't seem like it would be that difficult to port... Speaking from ignorance here though.
- juliangamble 12y agoYou can read more about the ClojureScript compiler here: http://swannodette.github.io/2014/01/14/clojurescript-analysis--compilation/ http://swannodette.github.io/2014/01/14/clojurescript-analys...
- chao- 12y agoAlmost everything I've seen about React makes me happy. However there are some parts for which I do not understand everyone else's excitement. This presentation contains a great example on slide 53 when it says: "No Templates!" With an exclamation mark, even! What it doesn't tell me, is what is wrong with templates in the first place? I happen to like them versus the feeling the alternative gives: Awkwardly-mixed-paradigms and using string concatenation while attempting to represent one language within another. Can someone who dislikes templates explain? Or maybe explain what a template means to you, as perhaps we're not all thinking about the same thing when someone says "No Templates!"
- danabramov 12y agoHave you seen Rethinking Best Practices video[1] from JSConf? I think it explains the point. [1]: http://www.youtube.com/watch?feature=player_embedded&v=x7cQ3mrcKaY http://www.youtube.com/watch?feature=player_embedded&v=x7cQ3...
- chao- 12y agoI have not. I will watch it soon and see if it changes my opinion. And I recognize it is just that: an opinion. A habit developed over time. But as a result, after all these years, I am also familiar with its advantages. The idea of "Data comes from X, gets passed to Y, and combined into a display", where "Y" gets stored in its own file somewhere, can be reused everywhere, and decoupled from whatever is passing it the data that will be displayed within.
- plorkyeran 12y agoThe general premise is that in practice templates usually end up very tightly bound to the view using the template, so you're not actually gaining anything by putting them in a different file and there's a lot of downsides to using a different language for templating.
- chao- 12y ago
- juliangamble 12y agoDavid Nolen (@swannodette) has been doing some great work in Om with ClojureScript and React. In addition to the links posted - this is a link on why ClojureScript's data structures (functional with structual sharing) make implementing undo trival in Om http://swannodette.github.io/2013/12/31/time-travel/ http://swannodette.github.io/2013/12/31/time-travel/ and this is a link on data binding in Om with :instrument http://swannodette.github.io/2014/02/27/taking-off-the-blindfold/ http://swannodette.github.io/2014/02/27/taking-off-the-blind...
- tylermauthe 12y agoOkay, I'm sold!
- thrush 12y agoIt would be useful to see side by side benchmarking and comparisons of typical Javascript vs React.js. I've just finished reading High Performance Browser Networking, and it appears to me that most client side code is slowed down much more by the network than the language. Am I missing something here? Is Javascript really that bad on its own?
- dangoor 12y agoIn my experience, JavaScript is quite fast in most browsers. Communication between the DOM and JavaScript is much slower and causing lots of layout invalidation and repaints absolutely kills an app's perceived performance. React's approach is simple for the programmer but takes advantage of the fact that JS is fast and minimizes those slow bits.
- whatthemick 12y agoI like the idea of React.js and immutable data. But i'm not a fan of the lisp syntax, am i missing something?
- axle_512 12y agoI used to have an issue with lisp syntax until someone pointed it out to me like this. In c and java like languages, you invoke a function like this: f(x) In lisp, just move the paren before the function name. What's the big deal? (f x) Similarly, f(g(x)) becomes (f (g x)). All we did was move the paren before the function name. The syntax is extremely consistent and it makes the lisp syntax trivial to learn. In nearly everything you do, the function name comes first the arguments come next. (+ 1 2) Here + is a function, and you are giving it 2 arguments. There are no special operators or syntax to learn. Just functions! The mind blowing part comes when you realize that this consistent syntax combined with the fact that the code is really just written in lisp datastructures, is what makes lisp macros so powerful.
- whatthemick 12y agoInteresting, that does provide a highly consistent base as you say. I might just have to try out Closure with Om/React for my next project.
- morkbot 12y agoAnyone knows more about "doing the rendering in web workers" part? Is it really possible? Someone doing it already? Any real benefits of that (web workers have their own overhead)?
- deleted 12y ago[deleted]