Ember.setState(this.get(React))
Alex Matchneer - 8/28 - Ember NYC
Who’s this guy
You may remember me from ng-embereño
“This is the only intelligent comparison I have seen of Ember & Angular”
Troy McClure�Hacker News User
React.js
The V in MVC… kinda
About React
So… what is React?
So what?
Aren’t there like a million JavaScript view layers out there?
Yes.
But it’s important to understand the philosophy behind many of React’s design decisions.
React Postulate 1
Managing state is treacherous
State management is difficult
React Postulate 2
Two-way bindings are evil
Two Way Bindings are Evil
Cue poor man’s XKCD
In other words...
Two-way bindings are like Ice Nine.
Read some Vonnegut if this makes no sense.
React Postulate 3
Data changing over time is the ultimate root of all evil
TL;DR: Everything is Difficult
So how is React designed to deal with all of this awfulness?
Uni-directional Data Flow: State vs Props
But wait...
...data needs to come back upward somehow, right?
Like,
what if a parent renders a child form? How does it know when that form was submitted?
Callbacks
Kinda like actions in Ember, right?
Yeah, naw, they’re just callbacks. They’re not events that keep bubbling or anything like that.
Cool
So what about state changes over time being the root of all evil?
In React, when you call setState...
...literally everything re-renders from that point downward
We’re talking giant arrays of stuff
OMG that sounds insane
Doesn’t that just kill performance?
No.
Doesn’t mess up scrolling?
No.
Doesn’t that mean needlessly tearing down and rebuilding DOM?
No.
WTF?
VIRTUAL
DOM
Virtual DOM
VIRTUAL
DOM DIFFING
Every time you call setState...
Hence
No unnecessary/expensive teardown of DOM
Hence
Scrolling doesn’t break (any more than it might with fine-tuned, granular DOM manipulation)
But you still rebuild / recalculate large objects / arrays?
Turns out JavaScript is fast, and that that part is rarely the bottleneck
What about diffing trees?
Isn’t that O(n^3)?
No, due to heuristics based on how you’ve built up your tree of components.
But first...
<Wat></Wat>
We have to talk about JSX
JSX is
JSX Examples
JSX
JavaScript
It’s all JavaScript
We don’t need no templates
Templates
Templates/rendering in Ember
Rendering in React
React Example
React Example
React Example
React / JSX niceties
React / JSX drawbacks
React / JSX drawbacks: example
React / JSX drawbacks: example
React / JSX drawbacks
Ember + Handlebars:
Because Handlebars isn’t “just JavaScript”, its syntax can stay presentation-focused; e.g. you don’t have to distinguish between lambdas and values
lambda
So, DOM in JavaScript…?
Seems like poor separation of concerns?
React authors argue the contrary:
Given the extremely tight coupling between the template and it’s context (a controller/component), the concerns are the same, and splitting the DOM into a template is an arbitrary separation of technologies rather than a legit separation of concerns.
Hence
In React, everything is a component.
OK, we get it.
Time to pop() the stack, but I feel it’s worth mentioning:
If you’re going to hate on React for some reason, make it something other than JSX
stack.pop()
[react, diffing heuristics, JSX]
stack.pop()
[react, diffing heuristics]
We were talking about virtual DOM diffing constraints and heuristics
There are some rules to abide by, now that we understand JSX.
Constraint 1: single element
“Constraint” 2: dynamic portions will be auto-wrapped
Constraint 3: provide keys to large lists
Side note: this error rules
Constraint 3: provide keys to large lists: why?
You have a list of players, sorted by name and you insert a player into that list. Commence DOM diff
Constraint 3: provide keys to large lists: why?
You have a list of players, sorted by name and you insert a player into that list. Commence DOM diff
Constraint 3: provide keys to large lists: why?
Lesson: you need to provide React with key=”” information when rendering lists, or else it won’t have enough information to efficiently update when you swap out arrays
Constraint 4: keys are required in other use cases
That’s about it for specifics
At this point you should hopefully decently grok the basics of React architecture
So what do I think?
I thought you’d never ask
machty’s thoughtz
machty’s thoughtz
If you love it so much why don’t you
steal all of its good ideas?
We’ll probably steal some ideas
but some of these good React ideas have some major caveats. Let us explore.
So, why does Ember
provide 2-way bindings if they’re so dangerous?
How evil are 2-way bindings, really?
and how crucial are they to the Ember programming model?
Two-way bindings can be evil, but...
What are these so called use cases?
Input fields
What about state change over time?
What does Ember do to help tame that beast?
First off, let’s just acknowledge that
we have clearly tamed that beast
Ember dominates the ecosystem of large apps
Whatever we’re doing, it seems to be working.
But specifically: Ember already has uni-directional data flow
and our bindings are live, so when upstream data changes, downstream changes too
But Ember has no unified setState
Unifying theme: there’s less typing in Ember
But many folk really like the explicitness of React.
“Is React scalable?”
“Yes, you dummy, obviously it’s scalable if Facebook uses it.”
but actually, it doesn’t take very long before you need to expand beyond the patterns built into React
Implications of Uni-directional flow
renderComponent(<App/>, rootElement)
(... miscellaneous top-level state …)
<CartDetailsPage />
<NavBar />
<NavCartOverview />
“5 items in cart
item 1
item 2…”
“5 items in cart”
Implications of Uni-directional flow
renderComponent(<App/>, rootElement)
(... miscellaneous top-level state …)
<CartDetailsPage />
<NavBar />
<NavCartOverview />
“5 items in cart
item 1
item 2…”
“5 items in cart”
Shared Cart Model
Implications of Uni-directional flow
Implications of Uni-directional flow
Implications of Uni-directional flow
Don’t get me wrong: this pops up in Ember sometimes too
But in a majority of cases, this is solved by KVO and model objects that live on a global store
“Global store? Seems pretty easy to throw one of those into React”
Yes, but it means leaving the happy React land of uni-directional data flow
Also
it isn’t enough to have access to a shared model objects; you’ll also need to manually subscribe to change events for that model, etc.
Enter Flux
React’s escape hatch
Facebook Flux
Facebook Flux
Implications of Uni-directional flow
renderComponent(<App/>, rootElement)
(... miscellaneous top-level state …)
<CartDetailsPage />
<NavBar />
<NavCartOverview />
“5 items in cart
item 1
item 2…”
“5 items in cart”
Some kind of global store; sideways flow rather than flowing down from top component
Alright Fancy Pants, but what about Ember?
Alright, wrap it up
I have to mention some cool projects
React Router (formally react-nested-router)
Om
Facebook Immutable Library
Final Thoughts
Thank you!
@machty