
Why you might not need MVC with React.js - peterhunt
http://www.code-experience.com/why-you-might-not-need-mvc-with-reactjs/
======
baddox
I'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
> "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
ractive.js (which I've been using on a couple of projects) also uses a shadow
DOM and learning it is shorter than this sentence.

~~~
pygy_
So does Mithril, which weights 8kB minified.

[http://lhorie.github.io/mithril/](http://lhorie.github.io/mithril/)

------
beat
Thanks 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
It'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
Do 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
It 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! :)

------
bsimpson
I'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.

~~~
davedx
This is exactly the problem we've been running into building a medium sized
interactive app in React. The management of data flow and state changes
through the component hierarchy with callbacks can get quite complex, and you
end up writing lots of callback boilerplate. So we've ended up rolling an
event system that sits alongside the React components, and a lot of our app's
interactivity is managed through the event system.

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.

~~~
peterhunt
This is exactly how react was intended to be used, and our larger apps use the
flux system architecture which closely resembles what you've described.
There's an example in the react repo. Om takes a different (but equally
viable) approach.

~~~
swah
Some links for folks that don't know what _flux_ is:

[https://groups.google.com/forum/#!topic/reactjs/mo0RWkg68vU](https://groups.google.com/forum/#!topic/reactjs/mo0RWkg68vU)

[https://github.com/facebook/react/tree/master/examples/todom...](https://github.com/facebook/react/tree/master/examples/todomvc-
flux)

Are caches (memcached..) an obstacle in the _flux_ architecture?

------
camus2
Well 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
React doesn't offer routing. The React TodoMVC implementation uses Director, a
separate library for routing: [https://github.com/tastejs/todomvc/tree/gh-
pages/architectur...](https://github.com/tastejs/todomvc/tree/gh-
pages/architecture-examples/react)

~~~
spicyj
You 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)

------
modarts
There'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)

------
williamcotton
MVC 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. :)

------
unspecified
The 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)

------
xixixao
There 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
In 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.

~~~
sbrekken
I'm using the exact same flow in my current project.

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.

------
dmbass
I 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
What 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
I 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
Even 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.

------
nevir
If 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
Isn't React a mostly pure DOM-based framework as well?

~~~
modarts
Not 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#reac...](http://facebook.github.io/react/docs/top-level-
api.html#react.rendercomponenttostring))

------
funkiee
Visiting this page on an iPad causes infinite font resizing and page layout
changes to occur.

~~~
e28eta
Same problem here. Scrolling a little caused it to stop flickering so quickly,
and portrait mode finally got it to stop misbehaving completely for me.

------
fiatjaf
I 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.

------
zackmorris
I'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.

~~~
mikhael
it's worth reading some of the early smalltalk/MVC stuff to try to understand
how MVC was originally formulated
([http://www.ics.uci.edu/~redmiles/ics227-SQ04/papers/KrasnerP...](http://www.ics.uci.edu/~redmiles/ics227-SQ04/papers/KrasnerPope88.pdf)).
it can be a little hard to understand, because it's pretty significantly
different from how most modern GUI toolkits work, but (as i understand it, not
actually having written smalltalk code) at its core it's fairly simple:

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.

~~~
inmodify
My $00.02 on MVC…

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.

------
mianos
It 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.

------
carsongross
I'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
Whoo hoo! Let's party like it's 2008 with intercooler.

~~~
carsongross
Get off my lawn.

------
gooserock
Um, 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.

------
gobengo
You 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.

------
ricardobeat
Some 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
Imagine 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
The 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.

------
puppetmaster3
This 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)

------
hayksaakian
The 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?

------
mrmagooey
I was under the impression this "application-state" issue was something that
the MVVM pattern was invented to solve.

------
jbeja
I use TaffyDB for models and Reactjs as controllers ,views and state
manipulation. Is good enough.

------
notastartup
I 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
[https://ghost.org](https://ghost.org)

There seems to be issues with some mobile clients that I cannot replicate on
my ipad and galaxy s3

