

React’s diff algorithm (2013) - tilt
http://calendar.perfplanet.com/2013/diff/

======
chenglou
Just a reminder: the best part of React isn't about its diffing algorithm or
the virtual DOM. Plenty of articles have been written on this (e.g.
[https://medium.com/@dan_abramov/youre-missing-the-point-
of-r...](https://medium.com/@dan_abramov/youre-missing-the-point-of-
react-a20e34a51e1a)). The diffing algorithm is a smart way of circumventing
the fact that the DOM is so slow; there's nothing to be proud of working with
such thing. Ideally your platform isn't so.

Web devs will keep reimplementing parts of React elsewhere; but at least, be
inspired by some other parts of React please.

~~~
moonchrome
>we can focus on examining React’s true strengths: composition, unidirectional
data flow, freedom from DSLs, explicit mutation and static mental model.

So wannabe functional programming in JS ? I always wondered why Facebook
didn't just go all-in on clojurescript when they did React, they have the
resources to deal with any compiler/technical issues, heck they could
reimplement the compiler themselves they already maintain a bunch of PHP
VM/language stuff. It does everything react tries to do but better and by
default.

~~~
nilliams
There are a huge number of people who don't enjoy programming in lisps and
don't buy the tradeoff that homoiconicity is somehow worth sacrificing all
syntax for.

You can take 'good parts' from functional programming without going 'all in'.
Many of us don't agree that the 'all in' is actually better.

(See Gary Bernhardt's 'Boundaries' talk [0] for an amazing explanation of what
I mean by taking the good parts of FP).

React isn't really about functional programming, it's very object-oriented.
And where the parent comment refers to 'composition', they mean composition of
components/view code, not pure functions as you may have interpreted it as.

Personally my dive into the Clojure community has been very frustrating, I
find very few answers on how to actually compose large apps, and the answers I
do find basically point back to OOP (but implemented in a syntax-less, ad-hoc
manner [1]).

If I've got this wrong, please tell me, I'm dying for better answers.

[0]
[https://www.destroyallsoftware.com/talks/boundaries](https://www.destroyallsoftware.com/talks/boundaries)

[1] Stuart Sierra - Components Just Enough Structure -
[https://www.youtube.com/watch?v=13cmHf_kt-Q](https://www.youtube.com/watch?v=13cmHf_kt-Q)

~~~
moonchrome
If you've actually seen the React wrappers in clojurescript they all look
really nice primarily because homoiconicity allows you to describe DOM as
clojure data (and clojure has a nice syntax for vectors/map literals which
helps with readability and parsing) for eg. you have stuff like [:div {:style
"width: 20px"} [:a {:href "#"} "blah"] "blah"] - that's more concise than HTML
and no need to fuse HTML with JS to do it.

Also you can keep that representation as datastructures, do operations on it
to transform and diff it, no need for custom objects or what not. Updates are
also really nice because clojure datastructures are immutable an mutation is
already isolated in to special constructs. The OO aspect of React is just a
sad consequence of JS - clojure has different ways to deal with polymorphism.

My impression is that all the stuff FB guys did (React, persistent data
structures, unidirectional dataflow) already exist or are more natural in
clojurescript than hacking it in to JS but I'm not the authority on the
subject.

~~~
chenglou
Are you suggesting to throw away a decade of front-end engineering in favour
of writing things in Clojure/ClojureScript? What's gonna happen next time a
new language comes up in ten years? Rewrite everything?

People (at least the ones I talk/work with) do understand the value of lisp.
And I myself am a defender of that Hiccup-style syntax
([https://github.com/facebook/react/issues/2932](https://github.com/facebook/react/issues/2932))
and a huge Cljs fan. But judging from this comment and previous, it seems that
you underestimate the value of getting work done in an already established
environment.

~~~
moonchrome
I'm just saying that they reinvented most of the stuff that you get from
clojurescript by default, and they did it in a more awkward manner because
they tacked it on top of JS.

Like they already have a JS preprocessor, have their persistent
datastructures, etc. and have to deal with a lot of stuff they wouldn't need
to deal with in a functional programming language.

~~~
yazaddaruvala
So I'm going to try and answer your original question:

> I always wondered why Facebook didn't just go all-in on clojurescript when
> they did React, they have the resources to deal with any compiler/technical
> issues, heck they could reimplement the compiler themselves they already
> maintain a bunch of PHP VM/language stuff. It does everything react tries to
> do but better and by default.

You're not correctly estimating the resources required. Every Facebook
endeavor I've heard of was an attempt to keep their millions of lines of
production code unchanged with the added benefit to have new code be better.
(eg. PHP->Hack, Untyped JS->Flow, DOM Manipulation->React, ...)

That said, perhaps you're not familiar with these types of codebases and
aren't quite grasping the magnitude of code change that would first be
required for Facebook to go "all-in on clojurescript". If you haven't had the
opportunity to participate in a codebase of that magnitude, there aren't
really words to describe it to you. Just know its multi man years worth of
effort. In practical terms its not possible because a business also needs to
iterate and release new features.

------
amelius
Nice explanation. I'm still wondering about something. Assume that I have one
big data model (the main state). I build my virtual DOM from the main state.
The states from all the sub-components are derived from this main state. Now,
something in the main-state is changed, but the change should affect only a
single sub-component in the tree. How does React know that only that sub-
component needs to be re-rendered?

I guess that it is still necessary to call setState on the sub-component, but
I suspect that the logic to figure out which component needs to be re-rendered
can become quite ugly, and prone to errors. Are they not addressing this
issue, or am I overlooking something?

~~~
masterj
> How does React know that only that sub-component needs to be re-rendered?

It doesn't. By default it will render the whole tree again. This happens in
javascript and is probably much faster than you think.

However, when an app grows large enough, this can be a source of performance
issues, which is why React provides ways you can inform it about work it
shouldn't have to do, namely shouldComponentUpdate. If you can compare the
data and determine that a particular sub-tree doesn't need to be updated you
can implement a shouldComponentUpdate callback that does this. Immutable data
that can be cheaply compared by checking reference equality is the preferred
way of doing this.

More info on this was recently added to the docs:
[http://facebook.github.io/react/docs/advanced-
performance.ht...](http://facebook.github.io/react/docs/advanced-
performance.html)

~~~
amelius
Yes, I'm aware that it is possible to go around this limitation. The problem I
have with this is that it kind of defeats the purpose of the library: keeping
the view logic in one place.

~~~
mikewhy
> keeping the view logic in one place

Each component has its own logic. If you are rendering your main app state in
child components you will be passing the state via props.

    
    
        var UserInfo = React.createClass({
          shouldComponentUpdate: function (nextProps, nextState) {
            if (nextProps.id !== this.props.id) {
              return true;
            }
    
            return false;
          }
        })
    

which makes perfect sense

~~~
amelius
Imagine I have a control with a large number (say N) of sub-components. Now
something changes in the state of the control, which corresponds only to one
of the sub-components. This change has to propagate to the right component.
However, the shouldComponentUpdate() function is invoked on each of the
components. This is O(N) work. This seems unreasonable.

To work around this, I could determine which component needs to change in the
parent control. But this would mean a separation of logic.

~~~
TheCoelacanth
But are you really going to have a single list of 1 million components or are
you going to have 1000 components that each contain 1000 components? The
second case is much more common and is handled just fine. If you really do
need a 1 million top-level sub-components, then you need to look at different
data structures other than just a flat list

------
amelius
Is it possible to automatically (without any additional code) animate the
differences between two versions of the DOM? This would make it possible to,
e.g., animate the creation of some space between two DIVs before inserting a
new DIV in between, and animate the removal of space when a DIV disappears.
This is something that is not easy in CSS alone, and could reduce much of the
flickering in web-pages which potentially makes users lose their orientation
(if the DIVs are large).

~~~
lobster_johnson
That's what transition groups do. When you wrap something I a transition
group, it will generate events when a child is removed or added, allowing you
to add required transition effects.

The CSS transition group is pretty useful: When a child is removed, it is kept
in the DOM, with a CSS "exit" class added (here you could have a CSS
transition for opacity, for example), and then finally removed when React
determines that the animation is done. Conversely, added nodes get an "enter"
class.

Transition groups are explicit -- you have to wrap your components in them --
and that's a good thing, as it allows you to control what kinds of transitions
are used in different contexts.

