practice

DOI:10.1145/2980991 performance. The key to both advances Article development led by queue.acm.org is that components built from stan- dard JavaScript objects serve as the fun- damental building blocks for React’s A discussion with Pete Hunt, Paul O’Shannessy, internal framework, thus allowing for Dave Smith, and Terry Coatta greatly simplified composability. Once developers manage to get comfortable with building front ends in this way, they typically find they can more readi- ly see what is going on while also enjoy- React: ing greater flexibility in terms of how they structure and display data. All of which caused us to wonder about what led to the creation of React in the first place and what some of its most ’s important guiding principles were. For- tunately for us, Pete Hunt, who at the time was an engineering manager at Instagram as well as one of the more Functional prominent members of Facebook’s React core team, is willing to shed some light on React’s beginnings. Hunt has since gone on to cofound Smyte, a San Turn on Francisco startup focused on security for marketplaces and social networks. Also helping to tell the story is Paul O’Shannessy, one of the first engi- Writing neers at Facebook to be dedicated to React full time. He came to that role from Mozilla, where he had previously worked on the Firefox front end. JavaScript The job of asking the probing ques- tions that drive the discussion forward falls to Dave Smith and Terry Coatta. Smith is an engineering director at HireVue, a Salt Lake City company fo- cused on team-building software, where he has had an opportunity to make ex- tensive use of both Angular and React. ONE OF THE long-standing ironies of user-friendly Coatta is the CTO of Marine Learning JavaScript frontends is that building them typically Systems, where he is building a learn- ing management system targeted at the involved trudging through the DOM (Document maritime industry. He is also a member Object Model), hardly known for its friendliness of the acmqueue editorial board.

to developers. But now developers have a way to DAVE SMITH: What is it exactly that led avoid directly interacting with the DOM, thanks to to the creation of React? Facebook’s decision to open source its React library PETE HUNT: Of all the Web apps at Facebook, one of the most complex is for the construction of user interface components. what we use to create ads and manage React essentially manages to abstract away the ad accounts. One of the biggest prob- lems is keeping the UI (user interface) DOM, thus simplifying the programming model while in sync with both the business logic also—in a somewhat surprising turn—improving and the state of the application. Tradi-

56 COMMUNICATIONS OF THE ACM | DECEMBER 2016 | VOL. 59 | NO. 12 tionally, we’ve done that by manually at how this new programming model manipulating the DOM using a cen- fared against both the Bolt model tralized event bus, whether by putting and our old event model. React ended events into the queue or by having lis- up really surprising a lot of people— teners for the event and then letting enough so, in fact, that it was shipped them do their thing. almost immediately as part of our That proved to be really cumber- “liking and commenting” interface some, so a few years ago we imple- on News Feed. That was the first big mented what we then considered to test for React, and that came a few be a state-of-the-art, DOM-monitoring years ago. system called Bolt. It was kind of like Then we tried it out on Instagram. Backbone with observables, where you com, which is where I entered the pic- would register for computed proper- ture since I was the person at Instagram ties that would eventually get flushed responsible for building a few things to the DOM. But then we found that using React. We were really happy with also was pretty hard to manage since it since it proved to be capable of run- you could never be sure when your ning our whole page instead of just one properties were going to be updated— small widget here or there. That gave us meaning that if you changed a value, a pretty good indication it was actually you couldn’t be sure whether it was going to work. Since then, it has essen- going to cause a single update, cascad- tially become the de facto way people ing updates, or no updates at all. Fig- write JavaScript at Facebook. uring out when those updates might TERRY COATTA: I’ve heard React takes actually occur also proved to be a really a different approach to data binding. hard problem. What sets React apart there? The whole idea behind React ini- PH: The way I think about data bind- tially was just to find some way to wire ing in a Web context is that you’ve got up those change handlers such that en- some sort of observable data structure gineers could actually wrap their heads down to the DOM nodes. The challenge around them. That hadn’t been the is that when you’re implementing case with Bolt, and as a consequence some sort of observable system, you’re we ended up with lots of bugs nobody obliged to observe this data structure could solve. So the engineers who start- wherever your application touches the ed working on a way to remedy that data model. ended up going wild for a couple of For example, if you use something months and came out with this weird- like Ember, everything you do is go- looking thing nobody thought had ing to use getters and setters, meaning any chance whatsoever of working. If you’re going to need to remain aware of you’re even vaguely familiar with React, this observable abstraction throughout you already know that whenever there’s the entire application. So if you want to a change in your underlying data mod- compute a value, you’re not going to el, it essentially re-renders the whole use a function only; you’re going to use application and then does a diff to see a computed property number, which is what actually changed in the rendered a domain-specific thing for Ember. result. Then it’s only those parts of the Angular, I think, does a much better page that get updated. job of this since it uses dirty checking, Some people here had some per- which means you can actually take ad- formance concerns about that, so vantage of regular JavaScript objects. an early version of React ended up The problem with Angular, though, is being run through a serious gaunt- that it makes it difficult to compose let of engineering tests where it got your application. That’s because, in- benchmarked against pretty much stead of using regular functions or ob- everything that could be thrown at it. jects to build up abstractions (as you

IMAGE BY ALICIA KUBISTA/ANDRIJ BORYS ASSOCIATES, BASED ON FACEBOOK REACT LOGO REACT ON FACEBOOK BASED ASSOCIATES, BORYS ALICIA KUBISTA/ANDRIJ BY IMAGE As part of that, of course, we looked would do with JavaScript), you have to

DECEMBER 2016 | VOL. 59 | NO. 12 | COMMUNICATIONS OF THE ACM 57 practice

er data you tell it to accept. That basi- cally allows for any structure. It could be something like Backbone. It could be plain JSON. It could be whatever PETE HUNT you want. Then your code will just go At a very high level, ahead and do whatever it’s supposed to do, backed by the full power of Ja- React essentially vaScript. At the end of that, however, it will treats your user return a value, which we call a vir- code as a black box tual DOM data structure. That’s basi- cally just a fancy handle for JavaScript while also taking in objects that tell you which kinds of whatever data you elements they are and what their at- tributes are. So if you think of data tell it to accept. binding as a way to keep your UI up to That basically pass everything through a scope in or- date with your underlying model, you der to observe those changes. Then you can accomplish that with React just by allows for any end up with this data binding that cou- signaling, “Hey, something in my data ples different parts of your program model may have just changed.” That structure. in ways that aren’t necessarily all that will prompt React to call the black-box clear or obvious. user code, which in turn will emit a For example, let’s say we’re look- new virtual DOM representation. Then, ing to sort a list of your top friends— having kept the previous representa- which is the kind of thing we do all of tion, React will look at the new version the time here. In order for us to do that and the old version and do a diff of the with an observable system, we would two. Based on that, it might conclude, have to set up an observer for every “Oh, we need to build a className at- one of the thousand friends you’ve tribute at this node.” listed, even if all we’re really looking The advantage of this approach is to do is to render the top 10. So, as you that it involves no actual tracking of can imagine, it’s going to take a good your underlying data model. You don’t chunk of memory to maintain that have to pay a data binding cost up whole representation. front. Most systems that require you to Obviously, there are ways to get track changes within the data model around that, but people typically just and then keep your UI up to date with break out of the data binding abstrac- that are faced with a data binding cost tion altogether at that point so they driven by the size of the underlying can proceed manually. Now, I generally data model. React, on the other hand, hate to say something isn’t going to pays that cost relative only to what ac- scale, but it’s fairly obvious this is go- tually gets rendered. ing to present some scaling issues. It’s TC: If I understand you correctly, clear that the bigger your application you’re saying React is in some sense gets, the more you’re going to run into a highly functional environment that this sort of edge case. takes some arbitrary input, renders an TC: I agree completely about the An- output, and then computes the differ- gular situation since I also find com- ence between the two to determine what position there to be tricky for just the it ought to be displaying on the screen. reason you mentioned—that is, you PH: Exactly. I like to describe this as end up having different parts of your “referentially transparent UI.” Which application essentially coupled silently is to say your user interface is generally via two-way data binding. But I see that a pure function of some set of inputs, React also has data binding, so I’m and it emits the same kind of virtual curious about how you’ve managed to DOM structure every single time for provide for better composability de- some given data input. spite that coupling. TC: So the data bindings that have PH: Let me zoom out a little here to caused us grief in Angular run in the observe that, at a very high level, React other direction here in the sense that essentially treats your user code as a they reflect the value of DOM elements

black box while also taking in whatev- that are bound to underlying model ob- ASSOCIATES BORYS ALICIA KUBISTA/ANDRIJ BY TREATMENTS ALL PHOTO

58 COMMUNICATIONS OF THE ACM | DECEMBER 2016 | VOL. 59 | NO. 12 practice jects or scope variables. Any changes there effectively become visible at multiple locations throughout your code at much the same time, meaning the composability issues surface since PAUL O’SHANNESSY different locations in your code are We end up writing made aware almost simultaneously of changes that propagate backwards good code pretty from the UI. PH: Another problem is that you much across the might have multiple bindings to the board since there same data source. So then which piece of code is going to be treated as the are fewer people authoritative source for determining going off into what the value ought to be? This is why, with React, we empha- crazy land writing size one-way data flow. As I said earlier, in several different ways. Do you think CSS. Basically, data in our model first goes into this that is an accurate portrayal? application black box, which in turn PH: It depends. There are certain this just gives us a emits a virtual DOM representation. places where React is very opinionated Then we close the loop with simple and others where it’s quite unopinion- way at the top level browser events. We’ll capture a KeyUp ated. For example, React is unopinion- to control all that. event and command, “Update the ated in terms of how you express your data model in this place based on that view logic since it treats your UI as a KeyUp event.” We’ve also architected black box and looks only at the output. the system in such a way as to encour- But it’s opinionated in the sense that age you to keep the least possible mu- we really encourage idempotent func- table state in your application. In fact, tions, a minimal set of mutable state, because React is such a functional and very clear state transitions. system, rather than computing a value I’ve built a lot of stuff with React, and then storing it somewhere, we just and I have a team that’s run a lot of recompute the value on demand with stuff with it. From all that experience, each new render. I can tell you that whenever you run The problem is that people some- into a bug in a React application, nine times want to have a big form that times out of 10 you’re going to find it’s includes something like 20,000 fields because you have too much state in that then bind to some simple keys there. We try to push as much mutable and data objects. The good news is state as possible out of applications to that it’s actually very easy for us to get to what I like to call a fully normal- build an abstraction on top of a sim- ized application state. In that respect, ple event loop that basically captures yes, we’re very opinionated, but that’s all the events that might possibly up- just because a lot of React abstractions date the value of this field, and then don’t work as well if you have too much sets up an automatic handler to pass mutable state. the value down from the data model I think Angular is actually less into the form field. The form and the opinionated in that regard, but it cer- data model essentially get updated at tainly has opinions about how you the same time. This means you end need to compose your application. up with a system that looks a lot like It’s very much a model-view-present- data binding, but if you were to peel it er type of architecture. If you want to back, you would see that it’s actually create reasonable widgets, you’re go- only simple syntactic sugar on top of ing to have to use directives, which an event loop. are very opinionated. TC: One of the things I’ve observed TC: Another thing I noticed right about React is that it seems to be what away about React is that it’s very com- people would call fairly opinionated. ponent-oriented. What was the reason That is, there’s a certain way of doing for going in that direction? things with React. This is in contrast to PH: We actually think of a compo- Angular, which I’d say is not opinionat- nent as being quite similar to a Ja- ed since it generally lets you do things vaScript function. In fact, the only

DECEMBER 2016 | VOL. 59 | NO. 12 | COMMUNICATIONS OF THE ACM 59 practice

Sheets). We strongly discourage the average product engineer from writ- ing much CSS. Instead, we suggest that they take these components off DAVE SMITH the shelf, drop them into whatever it is When I started out they’re doing, and then maybe tweak the layout a little. That has worked re- with React, ally well for us. PO: That way we end up writing good one of the hardest code pretty much across the board things for me since there are fewer people going off into crazy land writing CSS. Basically, to grasp was this just gives us a way at the top level this idea that to control all that. everything is For all the ways in which React sim- a component ... difference between a function and a plifies the creation of user interfaces, it component is that components need also poses a learning curve for develop- I found myself to be aware of a couple of lifecycle ers new to the environment. In particu- hooks about themselves, since it’s im- lar, those who have worked primarily getting lost in portant they know when they get added on monolithic systems in the past may relationships to or removed from the DOM as well find it challenging to adopt more of a as when they’re going to be able to get component-oriented mindset. They between their own DOM node. The component will also soon find that React is opin- components. is a fundamental building block on top ionated about how state should be of which we’ve built our own internal handled, which can lead to some hard framework. Now a lot of other people lessons and harsh reminders whenever out in the open source world are also people stray. building on top of it. We emphasize it because it’s com- TC: There’s a lot about React that’s posable, which is the one thing that appealing, but where are the sharp most separates React components edges that people ought to look out for from Angular directives and Web com- before diving in? What kinds of mis- ponents like partials and templates. takes are likely to make their lives more This focus on composability—which I painful? see as the ability to build nested com- PH: Most of the pain points are al- ponents on multiple layers—not only most certain to be about state. State makes it easier to see what’s actually is the hardest part of building appli- going on, but also gives you flexibility cations anyway, and React just makes in terms of how to structure and dis- that super explicit. If you don’t think play data, while also letting you over- about state in the right way, React is go- ride behaviors and pass data around in ing to highlight those bugs for you very a more scalable and sensible way. early in the process. PAUL O’SHANNESSY: This also has a TC: Give me a concrete example of lot to do with how we build applica- how people might think about state in tions on the server, where we have a the wrong way. core library of components that any PH: OK, I’m looking at a site powered product team can use as the basis for by React that was launched earlier to- building their own components. This day. It looks like the page has four main idea of using components is really components: side navigation, a search- just a natural extension of the core results list, a search bar, and a content way we build things in PHP and XHP, area containing both the search bar with the idea simply being to com- and the search-results list. pose larger and larger components When you type in the search bar, it out of smaller components. filters the results to be shown in the PH: Those product teams tend to be results grid. If I were to ask you where made up of generalists who work in all that filter state should live, there’s a kinds of different languages, which is good chance you would think, “Well, to say they’re not necessarily experts the search-results list is what’s do- in JavaScript or CSS (Cascading Style ing the filtering, so the state probably

60 COMMUNICATIONS OF THE ACM | DECEMBER 2016 | VOL. 59 | NO. 12 practice ought to live there.” That’s what intui- tively makes sense. But actually the state should live in the common ancestor between the search box and the search-results list, TERRY COATTA sort of like a view controller. That’s be- React is in some cause the search box has the state of the search filter as well as the search results. sense a highly Still, the search-results list needs access to that data as well. React will quickly let functional you know, “Hey, you actually need to put environment that in a common ancestor.” PO: If you were building that same that takes some UI with Angular and used a directive arbitrary input, for the search box and then another directive for the search results, you renders an output, would be encouraged in that case as ing more monolithic things, that often and then computes well to put your state in a common proves to be a problem. At Facebook, ancestor. This would mean having where we’ve always coded in PHP, the difference a controller hold the scope variable, we’re accustomed to building micro- since that’s where you’ll find the components and then composing between the two search text to which both of those them, so that hasn’t proved to be such to determine what directives would then bind. I think a huge problem here. Anyway, what I you’re actually looking at a pretty think we’ve always encouraged is that, it ought to be similar paradigm there. whenever you’re thinking about reus- displaying on PH: Good catch. But I think there’s ing something, break it down into its still a distinction to be made in that smallest elements. That’s why, in the the screen. React components are building example you cited, you would want to blocks that can be used to construct separate the comment box from the a number of conceptually different comment list, since you can reuse both components or objects. You could of those things in other parts of your use a React component to implement application. We really do encourage a view controller or some pure view- people to think that way. only thing—whereas with Angular, PH: We also encourage that you the controller is distinct from a direc- make stuff stateless. Basically, I like tive, which in turn is distinct from the to think people are going to feel re- “service,” which is how Angular de- ally bad about using state. I know scribes those things you shove all the there are times when it’s a necessary other logic into. Sometimes it makes evil, but you should still feel dirty sense just to make all those things Re- whenever you have to resort to doing act components. that. That’s because then you’ll start DS: In this case, if you were building thinking, “OK, so I really want to put the UI with React, what would be the this search state in only one place in common ancestor? A React component? my app.” Generally, that means you’ll PH: Yes. I would use React compo- find the right spot for it since you’re nents for everything. not going to want to deal with having DS: When I was starting out with Re- to synchronize states throughout your act, I think one of the hardest things application. And you won’t have to if it for me to grasp was this idea that ev- lives in only one canonical place. erything is a component. Even when I DS: What other major differentiators walked through an example on the Re- set React apart from other JavaScript act website that included a comment frameworks? box and a comment list, I was surprised PH: We haven’t yet talked about the to learn that even those were treated as idea that React, as a general way of components. I also found myself get- expressing user interface or view hier- ting lost in the relationships between archies, treats the DOM as just one of those components. I wonder if you find many potential rendering back ends. that to be a common problem for other It also renders to Canvas and SVG new React developers. (Scalable Vector Graphics), for exam- PO: For people who are used to build- ple. Among other things, this means

DECEMBER 2016 | VOL. 59 | NO. 12 | COMMUNICATIONS OF THE ACM 61 practice

React can render on the server without nology. It’s for ClojureScript, the ver- I should also point out that React booting up like a full-browser DOM. It sion of Clojure that compiles to Java- clearly is not purely functional. We doesn’t work like it’s just some other Script. What makes Clojure really cool also have some very imperative steps domain-specific language on top of is its persistent data structures, which and hooks that let you break out of the the DOM. Basically, React pretty much basically are really fast and easy-to- functional paradigm. But in an ideal hates the DOM and wants to live out- use immutable data structures. world, you don’t have any other sources side a browser as much as possible. I What that means for us is that if you of data, so everything is at the top and definitely see that as a huge differen- have a post on Facebook and some- just flows through—meaning every- tiator between React and the other Ja- body likes it, that gives you a new like thing ends up being a very pure output vaScript frameworks. event that should be reflected on the of these render functions. PO: We’ve basically seen the same like count appearing on that post. Nor- DS: A bit earlier, you used the term thing happen with WebGL or any other mally, you would just mutate that, but “referential transparency” to describe generic rendering platform. It just goes then you would have no way of detect- the way React renders UI. Can you ex- back to the question of immediate vs. ing whether the change actually hap- plain what that means? retained mode, where you soon discov- pened or not, which means you would PH: Basically, React components er that as long as you can output some- basically need to re-render the whole have props, parameters that can be thing, it really doesn’t matter. You just thing and then diff it. From that diff, used to instantiate those components. blow away whatever was there before. you would learn that only that particu- You might think of them as function DS: I’m also curious about the func- lar part of the UI actually changed. But parameters. In order to say, “I want tional programming aspects of React. if you were using immutable persis- to create a type-ahead with these op- In particular, I’m interested in know- tent data structures, instead of mutat- tions,” you can just pass in the options ing more about which specific func- ing the like count, you could just copy list as a prop. tional principles you’ve adopted. the story object and, within that copy, The idea is that if you render a com- PH: The truth is, we’re actually a update the like count. ponent using the same props and bunch of functional programming Normally, that would be a very ex- states, you’ll always render the same geeks. In part, that’s because if you pensive way to go, but in Clojure the user interface. This can get a little bit truly subscribe to the Church of Func- copy isn’t expensive since it has a way tricky, though. For example, you can’t tional Programming, you can get a lot of doing it where it shares the point- read from the random-number genera- of performance benefits for free. For ers with all the other parts of that tor because that would change the out- example, if your data model is serializ- data structure and then allocates new put. Still, if you handle this as a pure able and you treat your render method objects only for whatever actually function of props and state and make as a pure function of your properties, changed. That’s a good example of an sure you don’t read from anything else, you get server-side rendering and abstraction that’s quite complicated you can probably see that this is going to client-side rendering for free since under the hood and yet manages to make testing really fast and easy. You ba- both of those end up being pure func- present a very, very simple user inter- sically say, “I just want to make sure my tions of the same data on both sides of face—something that’s extremely easy component looks this certain way when the wire. That way, you can guarantee for people to reason about. it gets this data.” Then, since you don’t that when your application initializes, TC: I assume that could also help with have to take the Web-driver approach it will get into the same state on both undo/redo capabilities. of clicking on every single button to get sides automatically. That can be re- PH: Right. When everything is im- the app into the right state before dou- ally important if you have a very state- mutable, everything gets simpler. Om ble-checking to make sure you’ve got ev- ful kind of object-oriented mutative undos and redos basically just keep erything right... well, it becomes pretty system, since then it becomes much, around pointers to the previous state obvious how this makes testing a whole much harder to synchronize those two and the next state. When you want to lot easier—which, of course, makes de- states otherwise. undo, you just pass the old object into bugging easier as well. The other advantage has to do with React, and it will update the whole UI optimizing your apps. We have a hook accordingly. Related articles called shouldComponentUpdate, TC: The whole thing? on queue.acm.org where you can replace React’s diff al- PO: When your state is serialized into gorithm with a faster custom one. Also, one object at the top level, all you do is Dismantling the Barriers to Entry Rich Harris many functional programmers really pass that through and re-render it— http://queue.acm.org/detail.cfm?id=2790378 like to use immutable data structures and you’re done. With some of the Om examples I’ve seen, it just snapshots The Flame Graph since that lets them quickly figure out Brendan Gregg whether something has changed—just the state at every point and then gives http://queue.acm.org/detail.cfm?id=2927301 another example of how you can get you a UI that indicates how many states Componentizing the Web free performance benefits this way. you have. Then you can just drag back Taylor Savage TC: In the immutable data structures and forth on that. Or you could start do- http://queue.acm.org/detail.cfm?id=2844732 vein, one really powerful library I’ve ing some fancier things with the help

heard about is David Nolen’s Om. of trees to produce a really advanced Copyright held by owners/authors. PH: That’s a very cool piece of tech- undo system. Publication rights licensed to ACM. $15.00

62 COMMUNICATIONS OF THE ACM | DECEMBER 2016 | VOL. 59 | NO. 12