
React Fiber Architecture - wanda
https://github.com/acdlite/react-fiber-architecture/blob/master/README.md
======
Bahamut
This looks quite interesting - I got the impression that React would need
quite a rewrite internally to accomplish incremental rendering.

One thing I noticed with the priority mechanism proposed - Angular 1 has
something like this, but it turns out to be a complex api to understand and
use. In fact, just about everyone stays away from mucking around there, and
all usages of it I have seen in the wild is a straight up hack/misusage. I
suspect that something like this would increase complexity dramatically.

Animation is a problem I feel might be worth studying different systems on,
maybe not even just the browser. For example, Angular's implementations have
ended up mirroring how Chrome handles animations after collaboration with the
Chrome team. It probably shouldn't be singularly focused on how one browser
has implemented it, but studying these systems is probably best for maximizing
extensibility and performance.

~~~
mikekchar
Wow I'm at the bottom of the page and this is the first post about the actual
article. One thing I was wondering was whether the approach they are taking
might actually increase the complexity rather than decrease it. For example,
when writing games, it's pretty common to have your physics engine and your
rendering engine run at different frame rates. You get the incremental
rendering by separating the two. This approach seems to tie the rendering of
the internal model to the final rendering.

To be fair, I haven't really spend much time considering the JS animation API.
I suspect this is really what's at fault here -- there may be no easy way to
update the animation after the fact. Still, I can't help thinking that it
would be better to try to separate the screen rendering from the internal
model rendering...

~~~
yoshuaw
Yes, this was my thoughts also. I've got a hunch that concerns have been
incorrectly mixed here, leading to unnecessary complexity. But it's too soon
to tell for sure

------
jiaweihli
Can someone explain the benefits of React's DOM diffing model?

Rather than try to diff two DOM trees and optimize reconciliation, why not use
one-way data binding and update exactly what has changed, with 0
reconciliation cost? Either way, the upfront work - linking DOM elements with
model attributes - is the same. In JSX this is done by interpolating variables
into the template, and in one-way data binding this is done via data
attributes.

Anecdotally, I've found one-way data binding (using Rivets[1]) to be very fast
in practice for a view hierarchy ~10 layers deep.

[1] [http://rivetsjs.com/](http://rivetsjs.com/)

~~~
spankalee
I'm with you. All this complexity is baffling, when there's a very optimized
rendering engine sitting there in the form of the browser, and soon a suitable
component model.

If you wire up your components so that you just re-render the components that
have data changes, you get the benefits of dom diffing, without having to
diff.

You can skip all this framework JS, and just directly write an async-rendering
Web Component. It's pretty compact and easy to understand. I just wrote up a
sketch that would work with one of the incremental-dom-based template
libraries:

    
    
        class AsyncWebComponent extends HTMLElement {
          constructor() {
            super();
            this.isLayoutValid = true;
            this.attachShadow({mode: 'open'});
            this._foo = 'bar';
          }
          
          // Accessors could be generated with decorators or a helper library
          set foo(value) {
            this._foo = value;
            // You could check for deep equality before invalidating...
            this.invalidate();
          }
          
          get foo() {
            return this._foo;
          }
        
          connectedCallback() {
            this.invalidate(); // trigger the initial render
          }
        
          render() {
            // Call into template library to re-render component.
            // If the template is incrementally updated (say with incremental-dom),
            // then only child components with data that changes will be updated.
            templateLib.render(this.template, this.shadowRoot);
          }
        
          invalidate() {
            if (this.isLayoutValid) {
              this.isLayoutValid = false;
              // scheduleRenderTask enqueues tasks, so they'll be run in order down the component tree
              // A simple and correct scheduler is to just enqueue a microtask with Promise.resolve().then(task)
              scheduleRenderTask(() => {
                this.render();
                this.isLayoutValid = true;
              });
            }
          }
        }
    

edit: example uses. In a template:

    
    
        <async-web-component foo="[[foo]]"></async-web-component>
    

When the parent component renders and sets `foo`, the child will schedule a
task to re-render.

In JS:

    
    
        let e = document.querySelector('async-web-component');
        e.foo = 'baz'; // e schedules a task to re-render
        e.foo = 'qux'; // e doesn't schedule a task, because one is pending

~~~
underwater
Of course you can do manual dirty tracking. But why would you ever want to do
that on every single component when you could get it for free?

React's DOM digging has zero cognitive overhead so the benefits are
essentially free to me as a developer.

~~~
spankalee
This is a sketch of a raw custom element with no library for sugar. A library
that assisted in the pattern would presumably implement the accessors for you.

ES/TypeScript decorators would be an easy way to do this, or just a function
that fixes up the class after declaration.

~~~
underwater
So implement the accessors logic and invalidation logic, centralize the
rerender scheduling and you've rebuilt React.

------
gedy
This is very cool, but the nagging issue I have with React is this desire to
reimplement everything in JavaScript and bypass the Browser, DOM, CSS, etc.
I've lost track of what benefits this really offers?

~~~
sarahappleseed
I agree. All in the name of writing code that makes it easier to do what? Not
lose track of your own javascript?

~~~
coldtea
As if "losing track of your own Javascript" is something that:

a) does not happen

or:

b) is OK?

Might as well have written your sneer like: "All in the name of writing code
that makes it easier to do what? Simplify development?"

~~~
kensign
Well it doesn't simplify development and that's the point, it's not a clean
separation of concerns. It defies the whole purpose of using CSS, the DOM API
and keeping your javascript's structural patterns cohesive. This is why
Webcomponents are now part of the living standard. The browser runtime
nullifies whatever React was trying to achieve.

~~~
coldtea
> _Well it doesn 't simplify development and that's the point, it's not a
> clean separation of concerns._

On the contrary, it's very clean.

The real separation of concerns is between business logic and view code, and
React does that perfectly.

Not between HTML, CSS, DOM etc which are artificial inflated concerns due to
how the browser ended up as an ad-hoc application coding platform (from it's
"document" viewer beginnings, which is where the "D" in the DOM comes from).

(And of course nothing stops you from using CSS and external styles with
React, separating style from behavior).

> _This is why Webcomponents are now part of the living standard._

Web components only solve the non-interesting parts of what React does.
Namely, isolated components. All the state and management mess for the entire
app is still yours to deal with. Even React alone does more, nevermind
React+Redux/FLUX etc.

Which is also the reason React caught like wildfire, and nobody much cares for
Webcomponents (e.g. not any statistically significant numbers).

~~~
Silhouette
I generally agree with your position here, but I think you're giving React a
bit too much credit for separating business logic and view code. In practice,
anything complicated probably requires shouldComponentUpdate for acceptable
performance. Writing reasonably efficient shouldComponentUpdate in turn
requires underlying data that can be compared quickly, hence for example the
current interest in immutable data structures that can be tested for equality
by checking a single reference. And so the choice to use React for rendering
does have implications for how the underlying data is stored as well, which
undermines any claims about truly separating the view logic from the business
logic.

~~~
coldtea
Sure, all abstractions are leaky one way or another, but in the end React
gives you much better separation than what we had before.

Having to deal with shouldComponentUpdate is a blessing compared to having to
juggle 4-5 different concepts and web technologies, plus manage state, plus
separate logic yourself, etc.

Heck, in Backbone, which is as bare as it gets, and you needed to wrap your
data in specific classes...

And that's IF (and it's a big IF) you have some very complex performance case.
In most cases I never needed it, and tons of stuff can just be a pure render
function.

~~~
Silhouette
Again, I generally agree with your comments here. I just think it's important
to point out that this particular leak exists, because a lot of React advocacy
completely glosses over the point. The need to have a data model that supports
quick diffs one way or another has profound implications for the scalability
of your front-end code and it's an architectural decision that will be
expensive to change later if you get it wrong initially and learn that the
hard way.

------
toomim
What is the "incremental rendering" that this article is talking about?

~~~
timdorr
It's rendering part of the virtual DOM in one cycle, rather than the full
thing. This goes hand-in-hand with the ability to prioritize the rendering of
different components.

For instance, when you're scrolling through a large table, you may want to
prioritize the rendering of a custom scroll bar over the rows themselves. With
the Fiber architecture, you can do that so the scroll bar can hit a responsive
60fps and the rows can fill in when there are spare cycles.

~~~
toomim
Thanks!

------
iamleppert
Does it strike anyone else that the entire battle cry of react reeks of pre-
mature optimization?

Let's load a giant javascript framework, slow our onload and page ready event
by half a second, overcomplicate our build infrastructure with JSX, mixing up
our declarative code with non-standard imperative/functional javascript and
HTML, start importing sass and CSS into our javascript files, and use an API
that is weird and borrowed (componentDidMount?).

What exactly is the savings here? I fail to see it. When and if you have
100,000 DOM elements on a page and need to do efficient rendering and
reconciliation of what has changed? Poor code organization? Adherence to a
weird and clunky API? Because Facebook does it?

I'm sorry but I've had the displeasure of working on a few apps where
developers have used React and I could have done the same thing, without all
the bloat, achieving much faster performance, both measured from first byte to
when the page was ready for the user to use, to any interactions on the page.
All of these apps were relatively simple single page apps.

What has happened to us as developers that this sounds like a good idea?
Whatever happened to pragmatism? Has that just lost by the wayside of the new
shiny?

~~~
snarkyturtle
It isn't so much pre-mature optimization rather than having the next step of
the evolution of modern webdev.

Let's go back 6 years in webdev land. jQuery was king, Angular was the up-and-
comer. You have a fairly complex jQuery site probably rendering most things
from ruby or php. The only way to debug it was with console.log and refreshing
the page.

Angular comes around introduces modules and unit-testing, cool! You hook up
grunt and protractor, you install angular batarang. Everything is good. But
you end up building this huge angular app. You try to debug this edge case
when you have this panel open under this tab. You get frustrated that you have
to click on the same things over and over again. Livereload can inject css but
not js. When you change the html of your angular directive you have to reload
the page too.

This is where React comes in. React + Redux + Webpack makes it such that you
can apply livereload to _everything_. The css that your component imports, the
html it renders, what actions happen when you click a button. Everything. It's
not necessarily the new shiny rather than just the next step to making things
_easier_ for devs. It gets out of your way so you could focus on styling,
structure and business logic.

~~~
liamzebedee
Exactly! Not to mention the reusability benefits of components - rather than
passing around JQuery selectors and objects.

The cognitive load of using plain React is unparalleled for me. The effort to
setup the tooling is a bit of a hassle though..

------
amelius
So how does React know which parts of the model need reconciling, without
traversing the complete model and/or the complete state on every update?

~~~
acdlite
When you call setState on a component, only that component's subtree is
reconciled and re-rendered.

~~~
amelius
Okay. But how do you know what components to call setState on then? Is state
spread over components, or is it stored centrally?

~~~
acdlite
setState is a public API, usually triggered in response to a user event like a
click or an input change event.

State in React is local to a component, but it can be passed down to a
component's children in the form of props.

Centralized state can be achieved using a library like Redux, where an
individual component subscribes to an external data store's changes. Redux
abstracts the details away, but under the hood it's still just setState.

------
k__
Has this something to do with Preact, which started as an animation experiment
and became a React alternative?

~~~
spicyj
No, not related.

------
eatbitseveryday
And I clicked this thinking it was some competitor to Google Fiber, to
describe their networking architecture.

