Why you might not need MVC with React.js
code-experience.com
code-experience.com
Give it a year or so.
What's happening with React is different though, and happens only once in a very long while: engineering complexities that seem to have spun wildly out of control become radically simplified by something sitting right under your nose.
It's exciting. Congrats to all of those who have contributed to React.
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.
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 templateI 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.
(I'm not a particular fan of JS on the server-side yet..)
Even if I choose react for my view layer, I'm still going to need infrastructure for managing application state. View layer concerns are probably less than 30% of what I get out of Ember. The rest is bidirectional routing between URLs and models, meaningful controller hierarchies, etc.
React is simple because it ignores all that. But any significant app will still need to deal with those things.
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.
"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.
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?
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! :)
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.
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/co...
Anyway, I think a combination is what works best. I'm curious what others think.
a) It's in their official tutorial: 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.
I generally deploy these modules together to the web, and I want to keep the file size of my base layer small. I think React looks cool but I haven't gotten to the point where I want to send my users 30k more code when
It does seem promising for new projects. I hope to give it a go soon.
We're still learning, and are still not sure if we'll be using React for our production version of what's now a prototype. But I'm starting to feel more and more that we should use the strong points of React (the virtual DOM; so, send big CSS or DOM changes to the virtual DOM via state changes), and discard the other stuff (synthetic events, wiring components together via callbacks). It's tricky figuring out the best way to use it.
I'm starting to think that I would rather just have React as an "immediate mode rendering engine" -- a thin view library. In its entirety it feels too constraining.
https://groups.google.com/forum/#!topic/reactjs/mo0RWkg68vU
https://github.com/facebook/react/tree/master/examples/todom...
Are caches (memcached..) an obstacle in the flux architecture?
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.
It's very easy to integrate Backbone.Router into a project.
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".
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)
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. :)
- 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/
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.
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.
Shared data is stored in the state of a single component. Data propagates via props and since you've got a single source of truth you don't have to worry about data synchronization. To manipulate data, the component that owns the data exposes methods to children via context.
As a bonus, components become incredibly easy to test since both props and context are both explicitly passed to each component.
Pass the same state to both? The application state and the render state don't have to be trivial mappings of one another.
Rendering optimization is definitely a nice thing to not have to think about though.
"React implements one-way reactive data flow which reduces boilerplate and is easier to reason about than traditional data binding."
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 ;)
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.
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.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#reac...)
Things like 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.
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
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.
No, I'm not being sarcastic and I'm not being funny. The regard it is held in in some communities is radically out of proportion to any rational basis for it, especially the modern meaning of "MVC" which has been loosened to the point of near meaninglessness.
Model: business data
View: on-screen representation of Model; reacts to changes in Model to re-draw accordingly
Controller: maps user input to changes in Model; may need to interact with Views, and may pass control through a hierarchy of Controllers, to determine the Model being manipulated
in other words, user-input data flows as: C -> M, and M -> V. i see a Controller modifying a View (rather than just querying it) as impure MVC, and i normally strive to avoid it, even though that's essentially impossible if you're forced to use a platform's GUI toolkit.
i don't think of MVC as having "gone wrong," but rather that the name has been co-opted and the pattern corrupted by so many different people, in many different ways, as to make the original name extremely confusing. iOS' concept of "MVC" drives me crazy. i think it's probably fair to call it MVP (Model-View-Presenter), the difference being that the Presenter can indeed do some of the work of modifying the View. but i still mostly think of this as a hack: the more work that gets shoved into the Presenter, the more complicated it gets.
It's very interesting to see younger programmers speaking up these days. (No condescension intended; it just feels weird to be entering that old guy stage now, with 15 years of hardcore web/mobile application development experience) These younger guys are very, very sharp with enormous amounts of very cutting edge knowledge about current and quite advanced technologies. No doubt from the enhanced participation/availability model of example code the internet has undergone in the past 6-8 years (really since its inception, maybe it is just wider used now).
I think the keys to MVC for me are the logical silos by type. I don’t remember who first used the term ‘tier’ in this context, but I remember it back in 2000, possibly sooner with RUP to describe a multitier/n-tier application. This was a time of great debate online about the separation of concerns like data and security contracts of the newly developing web services… It had been mostly Cobra, DCOM and EJB’s up until this point. But I digress…
A very basic N-Tier architecture could be looked at like this:
Data Tier: This was the area that the core data logic and rules around the domain specific knowledge were guarded--and different from all aspects of the system. Like a phone company and their telephone number, as well as the number of minutes a particular telephone number is allowed, have specific requirements. The Data Model is where those types of requirements and rules are implemented.
Business Tier: Things like a father setting up time walled minutes on his daughter's phone so she can't talk on the phone at night... The data model would not allow even the business logic to set a negative number on the minutes; it would allow configuration of those domain model fields within proper bounds.
Presentation Tier: To make it easier on the user, we'll make the data entry screen telephone field on our external application format the input number to our specific carrier’s style: xxx-xxx-xxxx. The Business logic would handle events raised by the presentation tier and return a success message or possibly a failure message triggered from the business silo where the father hasn't paid his bill so the family management aspect of the program will not work until he does. Today, this will most probably be a JavaScript app responding to an asynchronous message from an open source web socket server, but it used to be good old request/response.
There’s all manner of debate as to missing tiers, level of complexity per tier or any manner of versions of good architecture. I've heard the database referred to as the Data Tier, when it was obvious the domain model rules require far more granularity and limitations than a simple database could provide.
However, from the above tiers, I think you can see where a M C V architecture begins to emerge from this separation of logic by the type of requirement it falls under. Why it’s ordered: MVC always boggled me—but I’m sure Fowler (aka Captain Obvious) could give us a reason.
The idea did not develop, IMO, from a need to over complicate a simple task, but rather from the large scale factory production mentality of early software shops. If you have the money for 20 developers for a very large project how can you separate their tasks by skill or experience so all their work will be countable like beans? Large engineering processes and tiered architectures, Business Analysts and Data Analysts, and even Architects and Silver tongued CEOs.
This was one of the uses of the whole front-end v/s back-end developer. I think this was a P.C. way of asking if you were an over glorified graphic designer with scripting skills or tier-minded.
Object oriented programming became appealing to some because with highly decoupled separation of concerns and fewer logical endpoints, abstractions could be applied. Every ‘Controller’ could extend an abstract class which could bake in the functionality to log all requests and responses for auditing purposes. You could abstract the data tier so its server load could be managed independently. You could even abstract the logic of the business rules into a new language which could be the savior or large enterprise wide service deployments: BPEL and ESBs.
Let me wrap up: In my opinion: MVC or MV* is a school of thought that has good use when one thinks in the context of the logical grouping of functionality by requirements and their type, with the ability to extend those types individually with functionality across their tier.
Same goes for the model. If you don't like to duplicate information for the sake of it, it's pretty straightforward to note that models on the client should be ... well, are a glorified caching mechanism. All these MV* models are in my opinion strongly hindering creativity and progress.
In this respect, I think React is onto something big.
If you want something even simpler than react.js: http://intercoolerjs.org
This can be done quite nicely using normal JavaScript and the DOM. Bubble up, invoke down.
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 ;)
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
I argue this is a design issue with the app itself. What good reason do various controllers have to communicate w/ one another?
p.s. what is the platform/library used to create this website? it's nice and clean.
There seems to be issues with some mobile clients that I cannot replicate on my ipad and galaxy s3