 So good afternoon. My name is Zian Cy and I'm a full stack developer at Reddit. So for those of you here expecting to hear a Ruby talk, clearly this is not it. This is actually a holdover from last week's Mountain West JS conference. I was slated to speak. I did speak and due to a number of technical difficulties, it was difficult to put forth the entire presentation. So this is kind of my bulging. So thank you for that. But before you tune out, I would mention that while the implementation we're talking about here specifically is in JavaScript, I would say the patterns and the ways of thinking about state and data really translate well regardless of what implementation is. I'll share that. In fact, I actually came from the Ruby and the Ruby on Rails world. And with that experience in mind, the ways and the things I've learned about React, which for the record is a JavaScript view layer, they really informed the way that I would architect or pattern any app, henceforth, be it in JavaScript or in Ruby or whatnot. So I really hope you just keep that in mind, even though we're not specifically talking about Ruby. So if you're here, you're likely familiar with some level, on some level with what Reddit does. You'll probably know about our Ask Me Anythings, our GIF exchanges. You'll probably hear about any number of initiatives or even the controversies that we're involved in. What you may not know about is that we recently, about a year ago, delved into the role of crowdfunding. We had an initiative that we called Reddit Made, which is effectively just crowdfunding for Redditors to create Reddit-type campaigns, be it like shirts, pins, vinyl toys, that sort of thing. And I was tasked with leading the engineering effort for that initiative. Now from a technology standpoint, Reddit Made kind of stood alone in terms of Reddit's products offerings, because it was really the first, but not the last, of our products to have a very deeply entrenched implementation of React.js. So what I want to talk to you today about is a little bit about what we've learned over the past year, working with React on Reddit Made, and talk about some of the complexities that we've come across, the challenges we've faced, and some of the successes that we've had. Now we'll discuss our rationale for why we've selected Reddit Made. I'm sorry, why we've selected React.js. We'll talk a little bit about our unique implementation or what I view to be a unique implementation of React.js. And then we'll talk a little bit about the title of this presentation, which is React.js as the MVC. Of course, if you're familiar with Ruby, you probably have some experience with Rails. You know what MVC is. What we've done, we initially kind of coined as being MVC, but as we sort of dug into it, it really turns out it's not quite MVC, it's not really MVVM, if you're familiar with that, it's something else entirely. So we'll talk a little bit about where we sort of ended up with all that. Now before I move too far forward, I do want to make note of a number of colleagues who are instrumental in this presentation coming into being. Again, I'm really more of a back-end developer. So I really relied on almost as a crutch, my two front-ends, who are phenomenal developers, and really this discussion we're having here is really the culmination of a lot of late night chats, aruminations, and that's how all this knowledge came into being. The first person I want to mention is Brian Holt. You may know Brian Holt, you may be familiar with his name. He's extremely prolific on the speaking circuit. If you've ever wondered about JavaScript frameworks, MVCs, be it Ember, Backbone, Angular, look up one of his presentations or talks. They're everywhere on YouTube. He also has a fantastic series on front-end masters entitled, Selecting a Front-End, rather, Selecting a JavaScript Framework. The second colleague that I want to call out is Dane Hansen, who's a phenomenal front-end developer who I've had the pleasure of working with for the majority of my professional career. If you've ever wondered about sort of low-level JavaScript if there ever was a thing, I think Dane would argue that there is a thing called low-level JavaScript. Check out some of his GitHub repos because they'll be very insightful and helpful in digging into that. So let's talk a little bit about the state of React and where we've come over the past year and a half or so. So just by show of hands, I'm just wondering, because we're at a Ruby conference, does anyone have familiarity with React at all? Okay, so a number of people. Has anyone actually implemented React into a code base? Awesome, okay, so hopefully what this is for the people who have experience is kind of like a brief refresher. And for those who don't have experience, maybe a high-level overview of what we're doing. But if you were here last year for Mountain West and you attended the JS session, you probably saw, remember a talk by a fellow named Pete Hunt, who I believe at that point was the engineering manager of React over at Facebook. And he gave a phenomenal talk where he discussed the origins of React, where it came from, the differences between React's implementation of the virtual DOM and other sort of observant systems, be it KVO or dirty checking, and really how React brought to the forefront a new paradigm for creating scalable and performant user interfaces. Now, I've watched his talk a number of times, as well as other talks that he's done in the year since. And I think really there's been an underlying current where I've seen a few key characteristics continually pop up that I think really set React, aside from other JavaScript frameworks or few layers. First, as the name implies, React is, of course, reactive. The way that React melds the concepts of the one-way data bounding and the virtual DOM ensure that data is always consistent even as the app is reactive. Then the way that React's view hierarchy is comprised of atomic reusable units of composition lends itself to a certain expressiveness that is both more comprehensible and understandable to the developer, you or me, as well as more efficient from a process and execution standpoint. Finally, React's implementation of the virtual DOM of rendering and of re-rendering is not only highly efficient from a technical standpoint, but because the canvas is repainted only if and where there's a diff in the virtual DOM, it provides a more seamless experience for the user. So just a word on efficiency, in his talk, Pete decided a number of performance benchmarks that affirmed that the rendering implementation of the virtual DOM outperformed KVO in all facets at scale with the exception of memory management, which is something now that can be mitigated either by caching or increasingly by JavaScript immutables. Now one other thing that Pete made clear was that his talk would be more about ideas and implementation. Bear in mind that this talk was a year ago and this was only a few months before React was first presented at F8 and maybe only about a year after React was first open sourced. So we were really talking about a different landscape back there. We didn't know what, you know, we kind of saw React as being a nascent platform whose applications and potentials were not yet understood, let alone realized. But today, for a year after all of this, we've had a year more learning, a year more tooling, re-tooling, building and breaking. I think at this point, we can really speak more intelligently, not only about ideas but about implementation, which is what I wanna do today. Let me again take you back another one year past to where Reddit was and more specifically where our e-commerce division was. So at Reddit, we run something called Reddit GIFs which is effectively our GIFs and Marketplace platform. And that platform had been built on a legacy Django stack that was about three years old at this point. So really what we found was that we were really beholden to the way that Django did MVC or the way they would term it as probably MTV. So, you know, we were looking at a system where data was always being marshaled by models where the controller was in charge of routes and the request response cycle. And finally, views were being rendered out using server-side templating. Now, that final thing in particular, the server-side templating started to really show cracks because as we started to scale, we realized that by rendering everything server-side, we weren't getting nearly as much performance out of the app as we needed. If anyone has worked in e-commerce before, you're well aware of that. If you're gonna take users, take customers and make them wait for things that they perceive as being very trivial tasks, be it managing a cart or updating addresses, they're gonna leave, they're gonna find another solution and they're probably not gonna come back. So, for a few months leading up to that point, we had been experimenting with Angular. And for those of you uninitiated, Angular was kind of a full-fledged, full-featured MVC, client-side MVC. Now, implementing Angular gave us a number of big wins, most notable in my mind, the ability to process asynchronously. But still, the implementation was a bit messy. We were conflating server-side and client-side rendering. At the same time, the dependencies on both the legacy and emergent stacks were getting more convoluted. They're growing larger and larger and the code base was getting a really difficult to maintain. So, when we turned our attention to this new crowdfunding platform, Reddit Made, we knew we had an opportunity to facilitate a sort of new, sleek, best of braid user experience. And we had the opportunity to build it from ground up. We identified a number of guiding principles. And in retrospect, I think a number of those principles have really stood the test of time and are sailing to this conversation here. We really wanted to simplify our code base. Our existing platform had gotten bogged down under the weight of not only just a growing platform, but under a myriad and mishmash of dependencies and DSLs, which ultimately resulted in a lot of issues for both technical as well as a developmental standpoint. At the same time, we're increasing our headcount, switching teams, switching functions. And what this meant was, effectively, that I'd be working on a front-end project on one day. Next day, I'd be working on the backend or even on the operations side of another. We'd reason that if we kept our code simple with Reddit Made, we'd be able to effectively just hot-swap developers in and out without much decrease in productivity. Of course, everyone wants their app to be performance, but performance always comes at certain costs. Now, we knew that we were working on a nascent crowdfunding platform. And by virtue of the nature and the newness of our app, we knew that we weren't gonna be dealing with the manipulation and marshaling of huge amounts of data. We weren't gonna be dealing with big issues having to do with concurrency. We basically knew that even at scale, we would never have to deal with a lot of the issues that, say, like an enterprise-grade e-commerce platform would have to deal with. Our particular brand of performance we knew would have to lie in the user experience. We wanted someone to come to our desktop or mobile website, sign up, create a campaign, and spread the word about their campaign so seamlessly and flawlessly that it would almost seem as though they were using a native app. Finally, we wanted to create a platform that behaved both declaratively and deterministically. What we wanted was to find a set of constraints, feed the app our data, and let the app manage that data all by itself. We didn't wanna rely on request response cycles to continually update our state. We wanted the app to effectively just marshal and keep its own state. So I've talked about our objectives. I've talked about how, a little bit about React's performance profile. So you can probably see where these sort of fit together. We knew that we wanted to, at a minimum, offload view rendering to the front end. And as we looked at the various projects out there, such as Angular, Ember, Backbone, it became increasingly evident that React's implementation and design pattern presented a lot of overlap with our objectives. So the title of my talk is React as the MVC. And even though I've already stated that MVC is not really the correct term for things, I hope you can understand why, when I was struggling to figure out what our implementation was, that it was an easy heuristic to latch on to. In fact, even on its own website, and this is from React's GitHub website, React is explained in terms of MVC. This is just the UI, and lots of people use React as the V in MVC. So we finally decided to go with React as our view. I thought of the missing M, I thought of the missing C, and then I panicked. If React is indeed the view in the MVC, where does the model and the controller come from? So here are a few alternatives. We have React on Backbone, or on Ember, or in some cases, Angular. We heard of developers replacing, or at least augmenting, Backbone views with React. Effectively, where Backbone would provide the, sorry, that React would provide the view layer, and React, Backbone would provide the data, and React would manage the view side. But this seemed inherently dirty. What we were doing was that all these frameworks that we had here were developed with native views built in mind and upon their own observation systems. Replacing all those native views with React seemed to us to be kind of an anti-pattern. And then there's React, the data API. There's a notion of letting React handle the rendering of the views, and pushing the business logic and routing to some external source, be it Django or Flask or Rails via an API. But this defeats our goal of owning the app state and cutting down on the request response cycle. Finally, there was React with server-side rendering. It's a very abstract alternative that dictates that. You inject React into the DSL template of some other sort of framework. In this case, or in your case, it would be ERB. And basically, that's conflating a lot of different things because then we have both server-side and client-side rendering, and that's basically a step backwards for all of us, for what we were trying to do, so we just took that off the table. So, as we looked at all the alternatives that were on the table, we started to formulate our heads and implementation that we hadn't really seen out in the wild. We thought maybe we could take React's functionality as a view layer and simultaneously extend its capability as a state manager. And in doing so, create a simple client-side framework that we could pass data to, and it would declaratively and deterministically know precisely what to do with that data each and every time, without the intervention of anyone but the user or having to go to, or having to access any sort of external resource. Now, after a lot of discussion, arguing and building and breaking, we came up with a high-level pattern which we felt like if we adhered to, it would enable us to build exactly what I had just described. The first thing we'd want to do is chunk the site into several atomic single-page apps. We want to identify functions or processes that take course over a number of adjacent page loads. For instance, the creation of a campaign. In our platform, it's you create a campaign, create a product for that campaign, then you add some details, three steps. But then you sequester all those functions into their own mini-app. What I mean by atomic is that the entirety of the data being handled and managed across that single-page app is self-contained and has no data dependencies that cannot be accessed that cannot be accessed from within the app. For instance, if we have an app for users to view and edit data that's pertinent to their profile, for instance, I'm sorry, we have an app where users can update their profile. Whether it's viewing the campaigns the user has created or changing the shipping address for a product they've purchased, all the data being loaded into the app, whether it's derived or explicit, belongs to that user, which brings us to the next point, which is that we pre-overload each app with data. When the app is initialized, we pre-overload the app with the entire universe of data that that app might possibly need. For instance, for users dashboard, he or she can do things like access and edit their saved credit card information, view past purchases or update the campaigns they've created. But even though they may not actually end up doing any of those things, we wanna pre-overload all the data they might need to do those things just in case they have to, so they don't have to make any sort of external calls to another API to grab that information. We wanna let each component manage its own data. Now, when I say component, I mean a React component. When you think of React component at the risk of maybe pissing off the React core team, I would liken it to be kind of a view model if you're familiar with MVVM. It's effectively just a reusable unit of composition, but whether it's a parent component, like a user or a sub-component, like a user's saved credit card information, let the component manage its own data. This means processes like updating and validation are carried out within the component itself and aren't outsourced to any other process outside of that component. And finally, we wanna keep the state of the app in the app until it's time to persist it to the storage layer. So once the component is finished managing its data, or the component is no longer needed, say because we've moved on to another page or to another app, and that is persisted in the app's master component. This is the component that keeps the state of the app across the duration of time that app is in existence. So in the case of updating saved credit card information, the user will update their info from within the payment component, which then initiates a callback in that master component, in that component's master component. Again, that's the app's record keeper with a copy of the saved credit card information. So once the app is closed or no longer needed, the master component will persist the data to the storage layer, which in our case is done by posting an API call to a data store. All right, so I know this is a little bit obtuse, so maybe a visual representation would help out. So this is kind of the data structure that we've created in React. At the very top, you'll see app.jsx. JSX, for those of you who aren't familiar, again at the risk of pissing off someone from the core team, is kind of just like a XML type abstraction for JavaScript is what we write React in largely. Now we haven't mentioned app.jsx yet. This is the root component that spans and manages all single stage apps that make up the site. It handles routing, which in our implementation is done using director.js and HTML5 push date. And it also keeps very high level data that's pertinent across the entire app. For instance, whether or not a user is logged in. Beneath app.jsx are many single page apps. Here you see two of them, campaign creation and user profile. Now don't forget, these components are components in and of themselves. Remember how I was talking about the app's master component? These are the master components in each app. Directly beneath each of the single page apps reside components that are effectively the pages within that app. For instance, personal info, big info, and user campaigns are all single pages within the larger user profile app. And finally, beneath each page component are the various components that make up the page. In the case of user campaigns, the subcomponents would be the campaigns that user has created. Each of these campaigns are themselves components, which in turn have more subcomponents, which in turn have their own subcomponents, their own, so on. So how does this actually manifest itself in practice? So this is an actual screenshot of user profile page in Reddit Made. But before we all go rushing to redditmade.com, which I wouldn't do if I were you, this comes with one big caveat. I say let's not do it because Reddit Made is no longer within our line of products. It's not for any sort of technical reason. It was basically because we decided to go, or Reddit as a corporation just decided to go more with our core line. And things like crowdfunding didn't quite fit into that mold. But the learning that we had throughout this experience really carried on and carries forth into Reddit's core lines. For instance, if you're familiar with the Reddit mobile experience, it's not really all that great. We're playing a huge re-event that's been years in the process. And we leveraged a lot of the stuff that we learned using React in Reddit Made. And you're gonna be seeing all that manifests itself when Reddit Made mobile web launches, I believe later this summer. So with that said, what you see here in red is kind of the representation of app.jsx. It's the entire app. Notice that it includes a header bar, which has information that's pertinent across the app, for instance, my name, and whether or not I'm signed in. In gold here, we outlined the single page app, which in this case is the user profile app. Again, this is the component that keeps a state of the app for the duration of its use. In black, we have the individual pages within this app. We have personal info, bank info, user campaigns. And then if we were to drill down, we'd see the individual campaigns that make up each one of these pages. So in this case, we have the campaigns page and the components within that are the campaigns themselves. So if anyone has experienced programming for iPhone, you're probably familiar with the way that the UI view hierarchy works. So this data structure that we have here, at least visually, is very reminiscent of the UI view hierarchy in iOS. From the architectural standpoint, it's very close in the sense that virtually everything you see here is a component that was initialized by another component, which was initialized by another component. Now, that's very much like UI views where a UI view is, spawns a UI view, which spawns a UI view, so there's ownership throughout that hierarchy. Where this differs is with data binding. Whereas in iOS, events that happen in descendant nodes are bubbled up to the top. In React, events that happen in descendant nodes at the bottom trigger callbacks in the ancestor node and those changes are manifested first in the ancestor nodes and then are trickled down through the rest of the app. So this unidirectional flow of data is an important distinction. It's really a hallmark of React and it's one of the reasons why React basically has a sort of consistency and reliability that it does have. So let's jump to some code here. Again, this is a very, very basic rendition of something that we may do, but I think it's representative of how we let React marshal its own state rather than outsourcing it. So what we do here is that we initialize app.jsx. Again, this is sort of the parent app. We have a router here which says, in this case, we only have one route, that's for profile. Again, this is very, very pared down. And then what happens is that we make one big call. So remember when I said that when we first load this app, we load in all the information that we could possibly need for that single page app. Well, this does it right here. And component did mount. We make an HX call out to API users. This pulls in all that user's information so that we won't have to make this call again regardless of what page we're on so long as we're dealing with users. So what this does is this sets on result here, on result sets a state, which you don't see here. But then what this does is this spawns off another component and that component is profile. So again, we have app at the very top and then this is the single page app itself. So when we have get initial state, the profile itself contains certain properties. For instance, for a profile would be email, first name, last name, those sort of things. Now for the sake of demonstration, we'll make one of the properties here times updated, which we'll see on line three up there. And we'll just keep a counter. We'll initialize that at zero. So basically what we're gonna do is we're gonna keep the state of times updated in the app itself. So even as we cycle through and make updates to the app, this is gonna marshal that data itself. It's not gonna outsource that. It's not gonna push it off to an API. It's gonna stay right here in the app. It's gonna stay totally consistent. So what we do here is on component din mount, we make one more call. We make a call for profile because profile has specific data that's relevant to the profile app that isn't part of users. So again, no matter what page we go to from the profile app, we have all the data we could possibly need whether we want to update campaigns, update payment information, look at prior histories, whatever. We'll have that information because we pulled from the profile here. And then we pass all those to this render function. And then we're gonna render out a component called personal infill, which is just one of the many pages that's in the profile app. We're gonna pass to it two things. We're gonna pass to it the times updated object here. And then we're gonna pass to it a callback that we can affect this parent component from the child. Okay, so this is personal info.jsx. So say we're gonna update email or first name or last name. This is where we do it. So we have in render here a little bit of markup where it says if we have email, let's go ahead and let the person update this and update their email. On change, we're able to use this on input change function to keep every single keystroke and marshal that data and keep that data in the app. And then finally, when you click on save click, we call the callback that it was originally defined in the parent component. We call that from this child component and that does that recursive loop. It passes, it fires off the callback in the parent function. And then that manifests a change and that change will eventually drip down and propagate throughout the rest of the app. So does that kind of make sense? It's one directional, like we don't go both ways. We just, there's a recursive sort of feedback loop where child components will just feed right back into the parent. So when we first started thinking about what this was, I initially said it was MVC because that was an easy heuristic, as I had said before. But I think that when we looked at actually what MVC is, we don't really have models, we don't really have controllers. Also, we don't have this two-way data binding that you see up here. So I don't really think it qualifies as being an MVC. Then again, I wanna sort of point out the distinction that we have between our implementation and a lot of what the single-page apps that you see out there being created by JavaScript frameworks do. First, I think a fantastic single-page app, for instance, would be Instagram's web app. So if you go to instagram.com, you'll see a feed. You can scroll down and you'll load more pictures into that feed. You can toggle modals, but really you kind of stay on that page. There's not really a whole lot you do there. It is really just a single-page app. When you wanna expand on that and you wanna think like, maybe we can take a JavaScript MVC and leverage that into more of a linear website where we have page one, page two, page three. We can step through, we can skip back and forth. I think that's where Angular comes into play because Angular does do that. But again, in Angular, each page is still kind of its own single-page app. You load page one, it loads up all the data, it fires back a request to store all that data, then it moves to page two, and it does that whole thing over again. So we're dealing with a lot of request response cycles that we're trying to cut out on. So I think that's kind of where we differ from, our implementation differs from the way that a lot of JavaScript MVC implementations work. Then there's React as MVVM. So that's model view view model, which is a little bit closer because if you look at a component, you can kind of conceive of it as being a view model. But again, we have this like two-way data binding, which we just don't have in React because we're not communicating between views and view models and models. Then we have React.js as flux. Now I don't know who here is familiar with flux. Okay, so I give a few people. Now flux is kind of a pattern. It's a library that Facebook came out with that works kind of in conjunction with React. Now I haven't used it myself, but I've looked at sort of the pattern that they've worked out here. And the most salient part is we're looking at the right-hand side where we have dispatcher feeds to store, to view, to action, and there's a feedback loop right there. So again, this kind of marshals its own data. I would argue that this is kind of a close pattern, a close architecture to what we've done ourselves over at Reddit. But at the same time, we're not actually using flux. We're not using dispatchers. We're not using stores. So I can't really say that this falls all that closely. So what does that really give us? I think for lack of a more succinct way of saying things, React.js is a state machine utilized in conjunction with one-way data binding to manage a series of single-page apps, which in concert act as a singular web platform. Now that's kind of tongue-in-cheek because it's way too convoluted to really express what I think we've really done kind of elegantly. So I don't really think that's a fair way of putting it, but as crude as it is, it really does express what we are doing. So in my most succinct words, what do we actually end up with? What we say by managing state across a series of interrelated apps, React.js facilitates a user experience that is performant, reliable, and programmatically simple and intuitive. So that's the long and short of it. Again, I know this wasn't a Ruby talk, but I hope that some of the things I've said about architecture and patterns will hold true. As a Ruby developer, I found that this kind of changes the way that I think about things. And hopefully on a certain level, it might help you also. That's it. Okay, yeah, so I know that I kind of should pour my way in here, but I think we have time for just a few questions. Yes, someone back? There are some JavaScript frameworks that are used to build mobile applications like Ionic. It's apparently optimized for Angular. I don't know a lot about it. Do you see a role for React in the future in building mobile apps? Not just mobile sites, but mobile apps? Mobile apps, you mean kind of like a polyfill? Well, across the platform, mobile application frameworks like Ionic. I can't really speak specifically to that. I know that we do use React in our mobile web implementation, but I don't really know of the usability of it across. I'm sorry, yeah, so if you watch the presentations from last week of the Mountain West JS, there's a fantastic talk about React Native. I encourage you to watch that because that very well may do what you're doing. That's called React Native. Anyone else? Okay, well thank you so much.