
How I learned to stop worrying and love React - kozlovsky
http://firstdoit.com/react-1/
======
logicchains
I encourage anyone who likes React and doesn't mind lisp to check out Reagent,
an awesome Clojurescript library built atop React that manages to completely
hide its complexity. It's by far the most fun I've ever had with web
development; the way I feel now is like how I imagine people who've had
religious epiphanies must feel when trying to show potential converts the
proverbial light of god.

[https://reagent-project.github.io/](https://reagent-project.github.io/)

~~~
findjashua
could you elaborate what specific complexities it abstracts away?

~~~
logicchains
It essentially combines all of React into a single component, the Reagent
atom. It's used exactly like a normal Clojure atom, but whenever it's updated,
Reagent will automatically update all Reagent components that depend on it. I
find this quite elegant, as it allows one to write pretty much any reactive ui
using only three functions: deref, update and render-component. Reagent atoms
can even be passed between Clojurescript async threads, and will still work as
expected, which completely eliminates the need for any kind of callback hell.

So what it eliminates is the need to learn React. Anyone who understands how
Clojure atoms work and how to use Hiccup-style HTML templating will be able to
use Reagent with almost zero learning curve.

~~~
findjashua
So Reagent is like React + Baobab
([https://github.com/Yomguithereal/baobab](https://github.com/Yomguithereal/baobab))?
Since Clojurescript has to compile to Javascript anyway, I can't think of a
reason why Javascript can't have a counterpart to Reagent.

I'm not familiar with Clojure, but it seems like atom is the data tree that
holds the state of the entire application. If so, could you give an example
use case of when you'd pass the data tree between threads, and what advantages
it has over promises or es7 async/await.

Just to be sure, I'm not questioning the validity of your claims, I'm
genuinely curious about how things work in reagent.

~~~
logicchains
There doesn't have to be a single atom holding the whole application, that's
just an approach some people take.

An example of passing data between threads: imagine a forum that allowed
indefinitely nested comments. It also loads comments lazily; one must click to
load a comment's child comments, in which case they'll be loaded from the
backend. However, if the child comments are minimised again, then expanded
again, another backend request won't be made, as the data is already loaded.

I approached this by having a separate 'thread' running that just listened for
messages (maps) on a channel. If it was a :get-children message, this thread
would check the local cache for the parent comment's ID, and if it found it
then it'd add the data to the atom provided in the request, otherwise it would
fetch the data, add it to the cache, and then add it to the provided atom.

The comment component would then take a copy of that channel, which it'd pass
to its children, and to get comment children data it'd just pass a :get-
children message into the channel with an empty atom for the other thread to
fill. If a button was clicked that changed a comment somehow, then it could
send a :update message through the channel with the parent id, and the other
thread would re-fetch the relevant data from the backend.

Of course, there's nothing here that couldn't be done with promises/async. I
just personally find Go/Erlang style message passing between threads to be
simpler and easier to reason about than async/await, and I believe
Reagant/Clojurescript would appeal to others who feel similarly.

------
jawns
I recently worked on my first React project, after working with Angular code
for a while. I'm willing to accept that as an app gets more complex,
React/Flux really pays off. But there's something to be said for having a
single template file for a single page in Angular, versus having JSX scattered
among 20+ components for that same single page in React. When you want to get
a 10,000-foot-view of how it all comes together, you can (generally) do that
in the code in Angular, but you're better off doing it in the browser with
React. Which may not be bad, but it's a difference worth mentioning.

~~~
fensipens
> But there's something to be said for having a single template file for a
> single page in Angular, versus having JSX scattered among 20+ components for
> that same single page in React.

Good point; How does one view the resulting react-page anyway? CTRL+U shows
<body><script.../></body> no matter what state the SPA is in..

~~~
ble
You want to look at the DOM structure of the page as it exists in the loaded
page and have I got a treat for you! Figure out how to open the web inspector
for your browser; the keyboard shortcuts are ctrl-shift-I or cmd-shift-I or
cmd-opt-I on a few (platform, browser) pairs.

(This will show you the actual DOM, not the React components... but since you
were talking about 'view-source', this might help you too.)

~~~
hirsin
Or hit F12, works in every browser and platform as long as the key is present.

~~~
hobby_body
Between Firefox, Chrome, and Safari on OSX, it only does anything in Firefox
(toggles Firebug).

------
ryannevius
I went through something similar...and then I found Mithril
([http://lhorie.github.io/mithril/](http://lhorie.github.io/mithril/)).

I may be alone on this, but I've enjoyed working with Mithril much more than I
ever did React. If you haven't given it a shot, I highly recommend you do.

~~~
tobr
What makes you like Mithril more? I've been looking at it for a while, and it
seems very nice and lightweight.

All I really want is an easy way to get performant DOM manipulations. With
React I have to build the whole view around the component system, which isn't
so flexible. Am I right in thinking that Mithril allows you to put the view
together any way you want, as long as the end result is an object it can diff
into the DOM?

~~~
nwenzel
D3 can do DOM manipulation a. It's more well known for its charting (SVG)
functionality. But I've used it to build tables and other data-based DOM
structures.

It's not ideal for all use cases. But for updating the DOM based on changes to
the data, I find it to be a useful option.

Square built and fast library on top of D3 called Crossfilter. Speed is pretty
amazing when you see the data source.
[http://square.github.io/crossfilter/](http://square.github.io/crossfilter/)

------
gadr90
Wow, author here. Woke up to a lot of unexpected traffic on the blog. I hope
you like this article. I took a long time to understand React and, now I do, I
hope other people don't take as long as I did!

~~~
matrix
Thank you for writing that article. To me, the article is pretty much how an
ideal technical article should be: it doesn't assume deep knowledge of the
subject matter and uses lots of examples and comparisons to make the case. It
takes a lot of work to write that sort of article, I really appreciate that
you took the time to do it. Looking forward to seeing the one about Flux!

~~~
gadr90
Thanks for reading! I'm glad you appreciate the effort. I spend an average of
eight hours to write one small post (1398 words)!

------
DougBTX
Nice overview, I like how the article has the same code demo in Knockout and
Angular to show how they both solve the same problem in slightly different
ways. Would be nice to see the firstName + lastName demo in React too, I know
the onChange stuff can be a little verbose, but would be good to show how it
can be used to actually update a single central model.

------
crimsonalucard
I've never used react but from what I read it's a more intuitive organization
of components.

The separation of the view and logic is an arbitrary separation that isn't
always efficient. It's like owning a bunch of power tools and organizing by
color instead of by function.

Templates have components like search bars and login forms and they have logic
related to those components. Why should component logic and template code be
separated when both the logic and template components serve the same function?
Code should be organized by segregating things into widgets. This, to me,
makes more sense.

I think the only thing missing from React is the ability to incorporate local
css styles into the widget. Again like I said if there are styles associated
exclusively with a widget, there's no point in segregating styles into some
separate css file.

Logic, structure, and style should be unified and organized by function, not
by category.

------
diminish
Question for experts: why Browsers do not get the idea of updating changes the
way react does automatically possibly with a start, stop transaction or better
without.

~~~
nathanaldensr
It would be wonderful if browsers acted more like game engines. Collect user
input and at the beginning of every rendering "frame", allow JavaScript to
process the input and modify a virtual DOM. Then, render the virtual DOM. It
would be so much easier to reason about web applications this way.

~~~
DennisP
I'm messing around with ideas for an experimental hypertext engine, now you've
got me tempted to try building it on a game engine. Looks like Unity might
have halfway-decent text support.

------
crazy_geek
It's the old Unix curses library approach applied to the DOM. Everything old
_is_ new again :)

------
msie
Ugh, for my sanity as a JS newbie I have to ignore all the other JS
frameworks/libs mentioned in this discussion and just master React and JS,
perceived warts and all. I recommend the same thing to other newbies who come
here.

------
mavdi
I finally got into React after being told by a friend for months that I need
to. I'll be honest the whole thing just looks like premature optimisation to
me.

I still find the structure of an angular app a lot easier to grasp, it might
be that I'm used to it but I remember the first time using Angular that it all
made sense to me. I liked it instantly. Coming from Backbone, it certainly was
a breath of fresh air. I can't say the same thing about React. Sure it's
faster, and if you think your app is going to mutate into something big,
consider using it. But I personally wouldn't make it my default choice.

~~~
todd3834
For me, it isn't about the optimization, it is about the way it lets you break
your app into simple reliable components. There was a moment when building my
first React application where it just clicked and I realized how much I was
enjoying the reusability and ease of testing all of my components. I have
never been able to write such well tested front end code. Also, the
reusability of my code has skyrocketed.

~~~
mavdi
Fair enough, I might need to spend more time with it. I certainly like the
idea of testing components individually.

------
vijayr
For someone whose strong point is not JS, is it a good idea to ignore all
other frameworks (like ember, angular etc) and just go with react? I find it
easier to evaluate server side frameworks than JS frameworks.

~~~
gadr90
Hey, "first do it", man :)

If you think React could be a good fit, simply use it. Comparing frameworks is
very time-consuming and doesn't get you any closer to your goals. Actually,
any framework is better than pause-deciding-which! :)

------
kozlovsky
> However, all template languages are inherently crippled: they can never
> achieve the same expressiveness and power as code. Quite simply, {{# each}},
> ng-repeat and databind="foreach" are all poor replacements for something
> that is native and trivial in JavaScript: a for loop.

On the other hand, when using a template language I can put `foreach` loops
and `if` conditions right into the template itself. And when using JSX I need
to calculate the result of a `for` loop before the actual template and it
looks much more complex and cumbersome.

~~~
insin
> On the other hand, when using a template language I can put `foreach` loops
> and `if` conditions right into the template itself. And when using JSX I
> need to calculate the result of a `for` loop before the actual template and
> it looks much more complex and cumbersome.

You can inline eqivalent JavaScript statements in JSX, without typical
template language limitations in terms of allowed expressions or scope:

    
    
        {this.props.foo > 5 && <div>...</div>}
    
        {this.props.foos.map(foo => <div>{foo}</div>)}

~~~
xtrumanx
You've gotta admit though that inlining isn't the usual case. Especially if
you're not using ES6 and the component your inlining is a few or more lines
long.

~~~
insin
That's not been my experience - multiple lines nest quite nicely - but even
when directly inlining isn't suitable (e.g. multiple if/else checks or
rendering a list in a way which doesn't suit a straight .map()) I prefer
creating another method and inlining the call to it, e.g. from my Hacker News
API clone:

    
    
        <ol className="Items__list" start={page.startIndex + 1}>
          {this.renderItems(page.startIndex, page.endIndex)}
        </ol>

------
vvpan
So, besides the virtual DOM, I feel like it's east to write React-like code in
Angular. Just make directives that are real tight, with unidirectional flow of
events and get passed only the values they need. Perhaps I'm missing
something.

------
JDDunn9
The virtual DOM is nice, although the only time I've seen a noticeable
difference from two-way binding in speed is for tables with 1,000's of rows.
The whole bit about React being more predictable than two-way binding is just
an opinion though. Since any component can emit an event and change data, it's
just as prone to loops and unpredictability. It's really just two different
ways of thinking through the process. One's not better than the other.

------
EugeneOZ
There is a lot of good and even awesome things in ReactJS universe, except
JSX. Thousands of developers took their lessons in PHP/Perl/Python about
mixing logic and representation, and now in nightmares they will generate HTML
from logic, especially by parts and in worst case - using conditional cases.
Everybody who tried to change design of website, written using something like
"if ($birthday) $html .= getBirthdayButton()", will understand me.

Maybe JS developers should go through it, through this circle of hell, to
avoid it in future, so JSX is necessary evil.

//despite of that, I sincerely thankful for people behind React, for their new
ideas and how they changed fields of JS frameworks and mobile apps. Big
respect!

~~~
tptacek
You might be confusing programming languages with concepts.

Don't think of React as "a container for logic and a system for doing views".
Think of it _solely as view logic_.

It's not mixing views with program logic. It's _only_ view. There's nothing to
mix. It just happens --- wonderfully --- to use a real programming language to
represent those views.

The notions of logic, controllers, models, storage, and all that jazz are why
there's also Flux (or Backbone or whatever else it is you want to use; we use
Flummox, it's fine).

~~~
EugeneOZ
You might be confusing "logic" and "business logic" terms, I talk about
"logic" exactly. Any logic and conditional cases makes design very difficult
to change, because you can't anymore just move one piece of HTML (tags) to
another place, or replace all classes with ctrl+f - it becomes very
complicated with logic used to build it.

~~~
tptacek
In practice, it is extraordinarily easy to move a React component from one
place in the UI to another, most especially if you're using Flux, so that
components are decoupled.

That's been one of my favorite things about working with React: it actually
_works_ to design bottom-up, factoring low-level components out and then
moving them around like cutouts.

I could _not_ do things like that in Knockout, or, god forbid, Mustache and
server-side templates; not without changing the application logic to account
for the move.

~~~
EugeneOZ
Components are made for code reuse - of course it should be easy to move them
:) They are encapsulated.

~~~
efdee
I get the feeling that you're just arguing for the sake of arguing. You can't
in one comment say that it's hard to move things around and then in the other
comment say that of course it's not hard to move things around.

~~~
EugeneOZ
Maybe if you will read my comments more closely you will see the difference
between moving parts of HTML inside component and moving components. "Moving
things around" is too broad term.

~~~
tptacek
The distinction you're making between "HTML" and "facility for encapsulating
generated HTML" seems pretty arbitrary.

I was making a simpler point, though.

Some of the reactions I see to React seem to come from the notion that it's
mixing application logic with view logic. That's an easy misconception to get
from reading the tutorials and quick-start documentation: after all, it's
using raw Javascript to generate HTML, which is the same language other
frameworks use for application logic.

The misconception comes I think from comparing React to Angular. Angular is an
application framework. React is solely a view framework. It happens that React
uses Javascript --- which works amazingly well in practice! --- to express
views. But that doesn't mean it's mixing application logic and view logic.

That's all I was saying. The semantic argument between "components" and "HTML"
is totally uninteresting to me. The important point, regarding ease of moving
"bits of UI" around, is that React makes it astonishingly easy to do that.
It's one of the selling points of React.

~~~
EugeneOZ
In my first response to you I underlined I don't mean business logic.

It's the example from "JSX in Depth"
([https://facebook.github.io/react/docs/jsx-in-
depth.html](https://facebook.github.io/react/docs/jsx-in-depth.html))

    
    
      // Input (JSX):
      var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
      // Output (JS):
      var content = React.createElement(
        Container,
        null,
        window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login) );
    

And it illustrates exactly what I'm trying to say: composing page from JS with
conditional logic. It's plague, because it will be painful to edit.

~~~
tptacek
I find it vastly, comically easier to edit React/JSX than templated Angular
and Knockout.

