8 ms·
Why you might not need MVC with React.js
- beat 12y agoThanks for this article. When I started playing with React (and seriously, I'm just playing right now), it felt to me like the whole MVC concept wasn't necessary, because I could just move state changes around to the correct places via the virtual DOM. But I'm not a front end guy at heart. I don't have the deep knowledge that the world of MVC masters do. I have a rule of thumb that when I find myself disagreeing with people I consider smarter and more experienced than me, I question my assumptions before questioning the experts. It doesn't mean I always bow to them, but I don't assume I am right because I'm so dang smart, even if that's the case much of the time. :) So when I find myself questioning the very necessity of a full MVC framework within the context of a React-powered application, I felt I should just withhold judgment for a while. This article by someone much more experienced than me lays out what I was feeling instinctively. Excellent.
- davedx 12y agoIt's nice to see people are finding React solves their problems, but keep in mind it's still very new tech. Be wary when you read things like this: "It took me a short time to get it and as soon as I got it, I felt like there is no problem that cannot be modeled decently with this system." I've been working with React for several months now, and do not have the same opinion. React solves some problems very well, but I'm not convinced at all that it solves application architecture better than "traditional" MV* JavaScript frameworks.
- beat 12y agoDo you have an opinion on blending it with other MV* frameworks, and what works well? I was originally thinking Angular for this work, but I liked working with React so much... would React integrate better into Angular, or Backbone, or something else? Again, not much of a front end guy. Last time I did serious front end was several years ago, when I spent 3 months coding in Sencha (and arguing with sloppy coders who liked the pretty Sencha widgets but didn't see the value of using the MVC pattern, grrr). I just want to be able to build a nice, modern front end with minimal grief, learning curve, or dogma. Is that so much to ask?
- davedx 12y agoIt depends on what you're building. Our app is very frontend/interaction heavy, but it's only reading data so we don't need much in the way of a framework to manage that. We're currently using React with our own simple router and event system to tie things together. If I had to try and break it down, I'd say something like this. Mobile/embedded app, or desktop app with heavy interaction/DOM changes: React, maybe some bits of Backbone Desktop app, forms and widgets/advanced controls: Angular Backbone is great because you can pick and choose bits of it, and it's very well documented code. Angular is nice for the complete "out of the box" solution for a web app; you get lots for free when it comes to testing too. I've not used other frameworks. YMMV. The best way to choose these is pick one and try it, and keep in mind sometimes you need to stick with it a while before you can really make an informed decision. Hope that helps! :)
- baddox 12y agoI've been doing a broad survey of these JavaScript frameworks for a month or so now. I've looked primarily at Ember, Angular, React, and Knockout. One thing is for sure: React has the community that feels the most "enlightened." I've watched several videos and read several posts similar to this one that express this sentiment of "when I finally understood it, it just clicked, and now I realize it's the best thing in the world." That excitement is certainly infectious, although I find myself wanting to hear "the other side of the story" from someone who dislikes React.
- RivieraKid 12y ago> "when I finally understood it, it just clicked, and now I realize it's the best thing in the world." There's very little to understand, it's really really simple. With React, I don't really see the point of Ember or Angular, they're basically zombie projects now. I wonder how their devs feel about React. React is an evolutionary leap enabled by their shadow DOM technology. Being able to rerender the whole page in a millisecond is a game changer.
- nailer 12y agoractive.js (which I've been using on a couple of projects) also uses a shadow DOM and learning it is shorter than this sentence.
- camus2 12y ago> With React, I don't really see the point of Ember or Angular React only deals with the view. In AngularJS, third party objects have a seamless integration with the view. Imagine you want to paginate datas. You'd write a Paginator component in React. In Angular you'd have a Paginator service holding pagination logic. Then you can have multiple representations of paginators,that would be logic less. It's better because it makes it easier to test the pagination logic in isolation,and you can then hide some complexity out of the view. i did it with a simple notification queue in a project i'm working on : .service('Notification', function($timeout, NOTIFICATION_TIME) { /** * manage notifications */ var onNotificationTimeEnd ; this.type = { 'SUCCESS': 'text-success', 'ERROR': 'text-error', 'INFO': 'text-info' }; this.timeout = null; this.current = null; this.notifications=[]; /** * queue app notifications * @param {Object} notif */ this.notify = function(notif) { if(notif){ this.notifications.push(notif); } if(!this.current){ this.current = this.notifications.pop(); } if(!this.timeout){ this.timeout=$timeout(onNotificationTimeEnd.bind(this), NOTIFICATION_TIME); } }; onNotificationTimeEnd = function(){ this.current=null; this.timeout=null; if(this.notifications.length>0){ this.notify(); } }; }); So each time a new notification pops , the view is updated just by adding {{Notification.current}} somewhere in my template I think React solve parts of the problem while Angular tries to solve the whole problem. I think there is definetly a middle ground between AngularJS and React virtual DOM that can be found. Let's remember that Misko defines AngularJS as "a better browser",not a framework.
- dmbass 12y agoI think this is a misrepresentation of what makes React.js valuable. React is useful for optimizing your rendering (model state -> DOM state) because you don't have to think about re-rendering sub-views of things that haven't changed. This has nothing to do with defining a communication flow for your app. You're still propagating state up and down your tree whether it is a tree of Backbone views or React components. Rendering optimization is definitely a nice thing to not have to think about though.
- PostingWithPSP 12y agoWhat do you mean? Child components don't pass their state to parent components. It's what allows React to be declarative. It's right on the front page: "React implements one-way reactive data flow which reduces boilerplate and is easier to reason about than traditional data binding."
- yazaddaruvala 12y agoI think when he said "propogating" he was simplifying, "use props to propogate state down the tree and use callbacks to propogate/change state further up the tree"
- PostingWithPSP 12y agoEven if that's a quote from the site, I still think it's just trying to explain what React is doing in a more digestible way. Any state belongs to one component. The extend of any "propagation" is invoking some function you've been given by your parent.
- camus2 12y agoComposite view management is made easy with React,much more difficult with string templates and Backbone views. There are Backbone plugins that help but they dont solve the problem at the source,innerHTMLing views is a bad solution to a difficult problem. What React doesnt solve is the relationship between the view and a model layer outside the view in an frontend application. AngularJS does solve that problem but it has an expensive cost. I think we live in an exciting time where problems like these are about to be solved. Someone,somehow will figure out how to do things the right way. I wish I could,not smart enough,sorry ;)
- nevir 12y agoIf you want a mostly pure DOM-based framework, take a look at Polymer, too (http://www.polymer-project.org/ http://www.polymer-project.org/). Web components seem to really embody what the article is driving at.
- platz 12y agoIsn't React a mostly pure DOM-based framework as well?
- catshirt 12y agoit is. one difference i think is that polymer seems to rely on Web Components API and shadow DOM. i guess subviews in React are functionally identical, but React does so without regard for the Web Components API. which has been fine with me. personally, i don't like seeing stuff like this in Polymer: <roster-list persons='[{"name": "John"}, {"name": "Bob"}]'></roster-list> and i like that React let's you write views without data-as-strings.
- saraid216 12y agoAs far as I've been able to tell, React and Polymer basically address the same problem. (And, unfortunately, each community is said to be dismissive of the other. So there's that.) My personal take is that, unless Polymer gets integrated into the browser, React is a better solution because it doesn't try to do custom DOM elements.
- modarts 12y agoNot really: a lot of its value is in the fact that the DOM gets abstracted away as "just another render target" (canvas, and perhaps even eventually native UI's could be potential future targets) React can fully render out to a string of HTML without any dependencies on a DOM implementation (for instance, if you're on the server) (http://facebook.github.io/react/docs/top-level-api.html#react.rendercomponenttostring http://facebook.github.io/react/docs/top-level-api.html#reac...)
- ricardobeat 12y agoSome code samples would be nice to really demonstrate what the article states. Conceptually I don't see much of a difference from what knockout and other data-binding libraries did in the past, or even an event-based system; React's breakthrough is really the virtual DOM and template system.
- ttty 12y agoImagine multiple nodes. In order to communicate between them, they need some kind of connection, this is coupling. When you have too many connections the application is hard to maintain and extend. The connections are all on the same layer, therefore is too confusing. Now think of a tree. Now imagine the nodes being some points on the branches on the tree. If one node want to communicate with another, it has to go down to the joint node and then go up to the target node. This will increase the indirection (and of course is less performant), you will have to pass data (and callbacks) between components but there are no global connections. In this way you make your application easier to edit and is less coupled. Hope you understood something (: maybe I will write a post with some images on my blog ;)
- nightski 12y agoThe connections are not all on the same layer in Knockout. It does not seem like you have ever used it? It uses a hierarchy/tree of binding contexts. For dependent values you have a computed binding which creates an implicit dependency which triggers a change whenever it's dependency changes. It works very well in my experience.
- camus2 12y agoWell you need a router and a way to persist data.Does React offer this? How do I manage page changes with React? React only concern is the view afaik. An app is more than a view,even in the client. So react is not MVC,but you still need MVC somewhere.unless you write one page apps of reactive documents. > It does not define how communication flows. I think it does ,in pure MVC: - view is stateless,view is 100% model driven. - controller gets events. - controller modifies the model. - model notifies the view to update. Of course that is in theory. In practice the view has states. The difficulty of "pure" MVC is that the model doesnt represent some data from the server or whatever, but the states of the view. The other problem is,in the browser,obviously the DOM has states. That's why MVC is not good for front-end dev,since it negates how the DOM works. Virtual DOMs are better as they embrace how the DOM works. And yes the DOM is a tree.Trying to reproduce a tree with Backbone views and underscore template is madness. Let's remember that MVC is a really old pattern ,created in a time where UIs were coded quite differently.
- baddox 12y agoReact doesn't offer routing. The React TodoMVC implementation uses Director, a separate library for routing: https://github.com/tastejs/todomvc/tree/gh-pages/architecture-examples/react https://github.com/tastejs/todomvc/tree/gh-pages/architectur...
- spicyj 12y agoYou can also use something like react-router-component which integrates very easily with React: https://github.com/andreypopp/react-router-component https://github.com/andreypopp/react-router-component
- dhruvbhatia 12y agoThe devs that created React are using React + Backbone.Router for Instagram's desktop site. It's very easy to integrate Backbone.Router into a project.
- catshirt 12y ago> So react is not MVC,but you still need MVC somewhere.unless you write one page apps of reactive documents. In that case I think ractive is easier to use than react. i think MVC is defined without regard for the number or pages or how said pages might be routed. you don't "need MVC somewhere".
- mianos 12y agoIt would be better to use a framework that actually renders on a phone like the Nexus 5 for an article on what's wrong with JavaScript.
- funkiee 12y agoVisiting this page on an iPad causes infinite font resizing and page layout changes to occur.
- e28eta 12y agoSame problem here. Scrolling a little caused it to stop flickering so quickly, and portrait mode finally got it to stop misbehaving completely for me.
- modarts 12y agoThere's been quite a bit of hyperbole thrown around about React lately (both positive and negative) but one thing that can't be overstated is the fact that the virtual DOM + React's diffing algorithm and the performance and architectural elegance it brings to frontend development is pretty amazing. I see parallels in the transition from c, to a Ruby/Python/C# development experience (where a lot of low level and error prone details are abstracted away, giving a developer a lot more expressive power in a higher level language)
- unspecified 12y agoThe article links to Facebook's example of a React app, which is available on JSFiddle [1]. I've been playing with using React: - without its JSX templating - with Coffeescript ...ever since I saw the idea here on HN a few months ago [2]. Here's the JSFiddle for that [3], I am a huge fan of the way you can pretty much write your DOM using (essentially) javascript functions. [1] http://jsfiddle.net/3Vs3Q/light/ http://jsfiddle.net/3Vs3Q/light/ [2] https://news.ycombinator.com/item?id=7232695 https://news.ycombinator.com/item?id=7232695 [3] http://jsfiddle.net/mFXVL http://jsfiddle.net/mFXVL
- zackmorris 12y agoI've never been a fan of MVC (I've used it for both php/backbone.js and iOS). My main problem with it is that the functionality of model is obvious, view is obvious, but controller can be anything from "a model for multiple views" to some kind of delegate, to an extension of the model. I find it so nebulous that even today, I can't explain to someone with 100% confidence where the model ends and the controller begins in their application. Contrast that with the front end/back end metaphor of the early internet, which was very easy for people to understand. It perfectly matched the way they had interacted with their bank, or command line tools, or even television. Hard to get much simpler than that! I think where MVC went wrong is that it tried to bring a portion of the back end (the model) into the front end (the view) and call it a “controller” without effectively explaining what that meant. To me, backbone.js seemed like mainly a cache of the server. As in, there are a multitude of other ways to do what it does, from XMLHttpRequest, to a nested iframe, to just manually writing a bunch of javascript that encodes the controller. I found that it simplified the easy work of translating from a rest API to objects, but did almost nothing for the hard work of choreographing how all the parts worked together. I never got far with Angular.js but my impression of it is that it replaces one complex choreography for another. My hunch is that the solution to all of this is a better data-object mapping that removes most of the code and works more like a graph, the way MS Access or Filemaker do, since most of the web is just CRUD apps anyway. The message passing of objective-c is an ok way to accomplish this, but it needs to be generalized and will probably work more like the Actor model: https://en.wikipedia.org/wiki/Actor_model https://en.wikipedia.org/wiki/Actor_model So MVC will be replaced with automatons that run in their own sandboxes and interact with each other through explicitly specified channels, the way that Go works. A high level example of this is that you wouldn’t encode a select box to be enabled/disabled based on a boolean in some JSON, but that the select box would simply be inaccessible for certain data because its container actor would be in another state. If you think about this, it mirrors how unix works, with a set of very simple functions and permissions that dictate what can do what. I was first exposed to this style of programming in HyperCard back in the 80s, then later in Flash and Unity. One thing I would change about it today though is to remove the notion of time so that it works like MS Excel or functional programming, so that all of the states can be exercised and unit tests basically become an enumeration of all the states you want the program to arrive at.
- williamcotton 12y agoMVC and Object Oriented designs have consistently been misapplied to various runtimes since their introduction and proper use in systems like Smalltalk and Self (I'm like a broken record if you know me at all). The MVC patterns in Ember and Angular have never made any sense. The only good thing about Angular are the directives. They made a big mistake in adding Services, Controllers, Filters, Routes and all of these super opinionated, bulky, slow things that aren't always needed. Ember suffers from similar bulk but the DOM/data binding is nowhere as elegant as Angular or React. Another great data-binding abstraction is d3. d3 is great for working with and displaying large data sets. It also does the right thing and keeps it's functionality simple. It's not trying to be the only abstraction in your tool belt. I've been using a home-grown abstraction for data retrieval and test mocks that has be loosely inspired by Angular's Services, but is much more functional in design. I'll release it in a few months once it has survived a few more iterations on this product I'm working on. It's called getIt. getIt and React. Get it? Every time someone sits down and decides to build THE ONE SYSTEM TO RULE THEM ALL... it fucks up... Mordor, the Soviet Union, Angular, whatever, same rule applies. :)
- xixixao 12y agoThere are two problems with React which I see at the moment: 1) Layouting 2) (more to the point of this article) what if your app isn't composed as a tree? More specifically, what if I have two tightly coupled components in two different places (physically and hence in the DOM), which need to share state? I don't want to have to go through a massive tree all the way to the root just to get that information between the two components work. I also want components which are reusable and some of this information flow make tight coupling between parents and children. There are certainly things to be figured out, React is no silver bullet.
- acjohnson55 12y agoIn a large Backbone project, I experienced this issue. Many people solve the problem with an event bus. To me, that makes debugging a huge pain and coupling rather difficult to analyze. I solved it by passing a single flat context object that provides the API exposed by all of the ancestors of a component. Components can either pass this context unmodified to their children or make modified copies to add to the API seen by their children. The advantage here is that intermediate layers of the tree don't need to know about APIs they don't directly consume, solving the problem of making every intermediary component mediate communication between parent and child. As for the somewhat more difficult problem of allowing distant parts of the app to communicate (say, A and B), the key is abstracting objects for holding application state and communicating changes across the app into a new component C, which must be held by a common ancestor D of A and B. D then becomes responsible for mixing C's interface into the context object received by all its children. Typically D should be a controller-type component, mostly existing to serve as the nexus for a subsection of the app. D might also be the top level app object. But partitioning concerns into separate components like C avoids bloating D, and yields a lot of flexibility. Other interesting patterns can be done as well. Optional hooks can be defined as context methods. The flat namespace of the context object also acts like a facade, decoupling the consumer of API methods from the actual provider. By making every member of the context a function (as opposed to data members), late coupling is achieved, which I found very useful in simplifying initialization dependencies. On the whole, I found the flat context to be extremely flexible, and developed a number of patterns for solving particular problems. I have an unfinished blog post on the topic that I may one day get around to.
- gooserock 12y agoUm, ChaplinJS (an MVC framework built on backbone) http://chaplinjs.org http://chaplinjs.org has done this sort of thing for two years. You have views and subviews, and you listen for events with @delegate (which maps to $.on using view's container) in each of those views. You almost never need to use global events, in fact it discourages their use.
- mrmagooey 12y agoI was under the impression this "application-state" issue was something that the MVVM pattern was invented to solve.
- carsongross 12y agoI'm glad to see people (besides DHH) finally beginning to question the necessity and/or wisdom of complex client side MVC frameworks. If you want something even simpler than react.js: http://intercoolerjs.org http://intercoolerjs.org
- coderzach 12y agoWhoo hoo! Let's party like it's 2008 with intercooler.
- carsongross 12y agoGet off my lawn.
- bsimpson 12y agoI've always been a fan of eventful programming. If something interesting happens, broadcast an event. If you care about a particular thing happening, listen for the corresponding event. It completely decouples all your components so long as the event API is consistent. React is composable. Cool. Why is it considered a best-practice to have ancestors pass callbacks to their descendants to modify state? I'd much rather see a component broadcast an event and have an ancestor listen for that event if it cares. That I have to pass callbacks through completely irrelevant intermediary components is just gross - the DOM gives me bubbling for free.
- gobengo 12y agoThis is a good summary of what is nonobvious to me, even as a full time JavaScripter. I generally try to stick to the ethos "Bubble events up, invoke down" wrt the object tree. I've never heard the 'pass callbacks to descendants to modify state' considered as a best practice, but I don't think that's bad either. It's a tool in the tool box. But it's not more of a best practice than other tools. DOM Event bubbling is pretty great, as it enables e.g. decorator patterns without having to replicate bubbling through your own EventEmitter system. But once you're passing a multiple callbacks down to all children, it's just tedious. It may be better to just pass a complex object (not a function) to your children. Tangibly, I think it's very reasonable for a ContentView (comment widget) to compose a Body Section and an Author Info section where both those latter two objects have a full reference to an EventEmitting Content Model. And they can call setters on that Content if they need to change the Content state and other Views would react. DOM Interactions bubble up to ideally as broadly scoped mediating controller as possible. I have currently been planning on refacotring parts of the following codebase, and planning on splitting this Class into a few components that would work like what's described above. https://github.com/Livefyre/streamhub-sdk/blob/master/src/content/views/content-view.js https://github.com/Livefyre/streamhub-sdk/blob/master/src/co... Anyway, I think a combination is what works best. I'm curious what others think.
- bsimpson 12y agoI called it a best practice because: a) It's in their official tutorial: http://facebook.github.io/react/docs/tutorial.html#callbacks-as-props http://facebook.github.io/react/docs/tutorial.html#callbacks... , and b) My friends who turned me on to React (as well as the StackOverflow that came up after a quick Googling) confirmed that you aren't supposed to create custom events in React, and should instead follow the callbacks-as-props model. If I've misunderstood something, I'd love to know the better way.
- gobengo 12y agoYou can have the both worlds of a reactive tree and MVC. Each node in the tree can but doesn't have to have a controller that react to external messages or event messages from it's children. Bubbling is a useful property of the event system of this tree. This can be done quite nicely using normal JavaScript and the DOM. Bubble up, invoke down.
- hayksaakian 12y agoThe first issue the author takes with MVC is overlapping concerns with controllers. I argue this is a design issue with the app itself. What good reason do various controllers have to communicate w/ one another?
- fiatjaf 12y agoI still miss standalone reusable components for direct plug and play into the app. Things like https://github.com/stevoland/react-bootstrap https://github.com/stevoland/react-bootstrap are not the best way of addressing this problem, I think. To use one of these components one has to plug the package in with npm, use browserify and JSX. I don't usually use npm or browserify, and write my components in pure Coffeescript, so I cannot use it easily. We should start making all-standalone really modular React components.
- notastartup 12y agoI really liked the article. I know that plenty of people are going to rip on it but I prefer ideas that stand out based more on individual insight than what the herd thinks (as the herd is usually wrong). p.s. what is the platform/library used to create this website? it's nice and clean.
- Retozi 12y agohttps://ghost.org https://ghost.org There seems to be issues with some mobile clients that I cannot replicate on my ipad and galaxy s3
- jbeja 12y agoI use TaffyDB for models and Reactjs as controllers ,views and state manipulation. Is good enough.
- puppetmaster3 12y agoThis is one of the best threads I have seen anywhere. I wrote a book on Struts MVC, and I agree that MVC in DOM is counter productive. Also 'my' answer is event buss similar to E/S: https://github.com/puppetMaster3/ModuleBU https://github.com/puppetMaster3/ModuleBU