React, GraphQL and Relay: A brief introduction
- select the contributor at the end of the page -
Angular.js has been the MVC framework of choice for top developers for years now but, thanks to Facebook engineers, this is changing in 2015. React is now claiming a big portion of the market, with huge players already on board including Netflix, Yahoo and airbnb, to name a few. React is often branded as the V in MVC, and it's arguably the fastest V so far; major frameworks (Angular included) have already learned from it. Facebook engineers are challenging both the MVC and the REST standards, and proposing radical shifts in the way we write Web applications. Here's what you should know.
What's inside what?
Instead of writing JavaScript inside HTML (for example, surrounding an <li> tag with a forEach loop over something, or doing things like ng-repeat and ng-if inside HTML templates), let's write HTML inside JavaScript--or, to be more accurate, let's write HTML using JavaScript. Having the complete flexibility of JavaScript to construct your HTML is liberating. It allows for even more declarative ways to describe dynamic elements, and gives you the super power of modularity. Clean HTML templates matter far less than the performance of your applications. In fact, performance is the primary reason you write HTML using JavaScript in React.
We all know that the Document Object Model (DOM) is the slowest bottleneck in Web development. And React offers a solution, using the Virtual DOM; since the DOM is slow in the browser, React represents the DOM in JavaScript itself. Now, when that set of operations is done, we have in JavaScript a "diff" of the Virtual DOM we had before, and the DOM we should have next. React applies that diff to the DOM, and continues on to the next set of changes when they happen. This proved to be a faster way than anything else in the same domain.
Of course, writing HTML in JavaScript isn't easy, so how can we continue writing HTML while still reaping the benefits of the Virtual DOM? Facebook’s answer is JSX. HTML is all about tree structures and attributes, and JSX allows you to take those structures and automatically convert them to JavaScript React function calls. With JSX, you write the views in the familiar and concise way you know (very similar to HTML, with minor differences), and then transform all JSX into native React before serving it up to the client (a process that can be easily automated). JSX is not required to write React applications, but it's much easier to write, read and maintain.
MVC: Good or bad?
Instead of the Models-Views-Controllers (MVC) architecture and concepts, like data binding between the views and the models, the front end system should have a one-way data flow. Your views should never change the models directly, though they always read from the models. And for writing, they trigger actions that eventually get dispatched to the models (the models are referred to as "stores" in this flow). React fits perfectly in this flow because of the way it reacts to data changes in the stores (since it's always listening to them), and re-renders the views efficiently (thanks to the Virtual DOM).
So, what exactly is wrong with MVC? On a small scale it works well, but when your application grows into multiple models and multiple views, the relations between them get complicated. Any view can read from and write to any model--and with auto-binding, models could write to other views, which in turn will do their own writing. This back-and-forth flow could cause a cascading update, and while it can be avoided with good code, the idea of things going in multiple directions is scary. The solution is in verifiable constraints; having an enforced one-way flow is the smart alternative. Anywhere in the application, you know that there's only one direction to go. The Flux pattern is an attempt to explore this idea, and it works like a charm.
GraphQL
Instead of REST APIs, have the client ask for exactly what they want (using a graph), and have the server parse that graph (with just a single endpoint), and respond with exactly what the client requested (no over-fetching, no under-fetching). GraphQL is a great fit for that graph with which the client can ask the server.
Let's assume the response will eventually be JSON (it doesn't need to be, but we're not scratching that standard yet); a JSON will be a set of keys and values (more or less, with nested sets and an array of sets). We know that values will come from the server. The keys, on the other hand, are exactly what the view is using (as in render the person.name here, and the person.address there). So, if we strip the JSON response from all the values, recursively, what we're left with is that weird keys-only, data-less JSON; simply a GraphQL string. GraphQL is much more than that, but we can't do it justice here, so look for a blog post about it soon.
RelayJS
Instead of the standard recommended separation of data and views, and since only the view knows exactly which data elements are needed to render correctly, do not separate these two at all. Instead, co-locate them and have the data requirement expressed directly in the view component itself. This will allow a view that renders 10 names and addresses, along with phone numbers, emails and social links, to ask the server for ALL data in one trip, and get back exactly what it needs.
GraphQL can be used to express the data requirement, and a GraphQL server will put values on those GraphQL keys. But the beauty doesn't end there -- what if an action triggers a data need for multiple views? Since we have one endpoint to talk to, we could merge our graphs. But then there's the complexity of that merge, dealing with data when it comes back, and making it available to React components through properties, among other things.
This is where RelayJS comes in. Basically, it's a framework to manage these operations, and other data mechanics like pagination, filtering and sorting. With Relay, you declare the data required by every component with GraphQL, and Relay figures out when and how to fetch it. Relay also aggregates all the needed queries into efficient network requests and gives the components exactly what they need, when they need it. It also manages write operations with GraphQL mutations, and offers consistency, optimistic updates and error handling. Relay builds on top of the Flux pattern and reduces the pattern into one store, handling the cruft previously needed for manually preparing and dispatching actions.
Learn once, write anywhere
React Native lets you apply the same knowledge that you learned with React, but instead of targeting Web components, you target view components that translate natively to iOS and Android apps. In a nutshell, you get the best of both worlds.
When used together, React, GraphQL and Relay form an amazingly strong stack, which I like to call RGR. The RGR stack could blow REST away for good, and push the MVC pattern to the edge of extinction. In a few years, writing MVC applications on REST endpoints might be a thing of the past. The React Native framework has the potential to dominate native application development and leverage shared endpoints with matching Web applications. Bottom line? Writing native applications is hard, React Native is uniquely positioned to change that for good.