I gave a talk about React at BrazilJS few days ago. The "slides" are here. In this post I'll go over what I said (more or less) at the beginning of the presentation. I hope to follow up with some more code.
Disclaimer: I work at Facebook. But these are my thoughts. In fact, I may have gotten some things wrong. I was in no way involved in building React, these are opinions of a developer trying to build a thing or two with React.
Active Apps vs. Passive Pages
The applications are different. The application data and content changes constantly - from user actions, from new data coming from the server or simply with the passage of time.
On the web we build web applications using the DOM. Not that we wanted to and not that the DOM was designed for todays applications (after all it has a "document" in the title). It's just something we ended up with. So today we're using DOM and our applications need to keep modifying the DOM all the time, over and over again, to create those rich experiences.
And we all have a love/hate relationship with the DOM. On one hand it's easy and familiar and seems to do the job.
On the other hand the DOM API is verbose. We spend a lot of time just hunting for the nodes we need to modify (like
getElementsByTagName). Then once we have found the nodes, we start doing cycles of
appendChild to update those nodes.
Also DOM modifications are slow. The browser needs to repaint and reflow, which are costly processes, so we need to be careful when touching the DOM. Often recommended practices are to not read from the DOM all the time, to batch DOM operations and so on.
Then there are the event handlers - you need to make sure you cleanup event handlers attached to nodes you remove, to prevent memory leaks.
This is where React comes in to offer an simpler way of building UIs. React lets you build your application using components that know how to render some data. When data changes, components update automatically in a very efficient way, only where necessary. And all the job of attaching and detaching event handlers is taken care of for you. Also efficiently - using delegation.
Think about the last time you needed to create a table from an array of data.
var table = document.createElement('table'); var tr = document.createElement('tr'); var td = document.createElement('td'); var text = document.createTextNode('some data'); td.appendChild(text); td = document.createElement('td'); text = document.createTextNode('some more data'); td.appendChild(text); tr.appendChild(td); table.appendChild(tr); // .....
Gets pretty annoying pretty quickly.
And then one the table cells happens to be a link. Oh, man, there we go again...
createTextNode, append to the link, append to the
td, append to the
Then a single letter in a single table cell changes. What you're going to do?
- Do you keep references to all nodes, to all objects? That's insane.
- Do you traverse the table hunting for the node? Gimme the 3rd cell in the 5th row? This would be often inefficient, remember, the DOM is slow.
- Do you rebuild the whole table? This is probably the only sane option. It will be inefficient (reflows, repaints of a big chunk of DOM). And what if there were event handlers on the cells? Or an input that user has typed in already.
In React's case you say:
- I have this little component here called Table with Rows and Columns children
- I have an array of data
- Deal with it!
Then something in the array of data changes? Here's the data, React, my dearest - deal with it.
So how does exactly React deal with it internally? Two crazy ideas - virtual DOM and synthetic events.
What about event handlers? They are synthetic. React uses event delegation to listen way at the top of the React tree. So removing a node in the virtual DOM has no effect on the event handling.
The events are automatically cross-browser (they are React events). They are also much closer to W3C than any browser. That means that for example
e.target works, no need to look for the event object or checking whether it's
e.srcElement (IE). Bubbling and capturing phases also work cross browser. React also takes the liberty of making some small fixes, e.g. the event
<input onChange> fires when you type, not when blur away from the input. And of course, event delegation is used as the most efficient way to handle events. You know that "thou shall use event delegation" is also commonly given advice for making web apps snappy.
Go check React out. You might like what you see. You can also read some more on "why React" here.