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?
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.
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.
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.