If you're a javascript developer who finds themselves writing code to help manage an interface, I would highly suggest taking a look at React JS, and pulling up a chair to the cool kids table.
When it comes to client work, I've always enjoyed the pace and variety of projects. With multiple new projects per year, you're able to begin anew, utilizing new technologies and patterns with with each start. In 2015, Authentic was able to work on many new projects. On several of these, we took the opportunity to learn and utilize React JS, the oft mentioned fancy javascript framework released by Facebook back in 2014.
In this article I want to provide an introduction to React JS, for those of you interested in the latest and greatest, but potentially a little hesitant to jump into something so new and different.
Angular, Coffeescript, Backbone, Ampersand, Ember, React... All unique flavors of javascript. Some frameworks, some libraries, some languages in themselves. Where does React fit in?
Unlike Angular, React is not a full-service client-side framework. Angular provides its own propriety libraries for routing, models, and services; React does not. React considers itself to be a View library, concerning itself only with the display and interaction of your interface. Routing, events/messaging, storing and syncing data are all things outside the realm of React.
Being so light, from a responsibility point of view, allows React to be easily implemented into existing projects. If you have an existing, potentially bloated, codebase it's rather easy to plug in React. You’ll see big improvements without needing to completely replace the entire client-side of your project.
At Authentic F&F we've used it for building interfaces on SASS products, implementing unique ecommerce checkout workflows, and are now in the latter stages of using React Native to build a native iOS app.
Before jumping into a React project, be sure you have a grasp on the unique concepts React brings to the table. These concepts aren't uber-complex, but React is a very opinionated library, and you'll want to be aware of these concepts before starting. The React documentation does a great job of explaining the core tenants.
Previous to React, I was used to less opinionated client-side frameworks like jQuery and Backbone. Both of these libraries give the developer a plethora of tools to architect their front-end, but not necessarily strict conventions for implementing them. They provide the mechanics, but not best-practices.
With React, you get both. A library with a strict set of responsibilities (only managing the View), and an easy to understand architecture, abstracting much of the boilerplate code necessary for creating a dynamic interface. This combination keeps code lean, compartmentalized, and very testable.
From a technology point of view, React requires a few modern javascript tools you'll need to become familiar with. Tools like Babel, ES6, and Grunt/Gulp are necessary to get React up and running. Though there is an initial learning curve for the setup, if you're familiar with Grunt/Gulp, you're already halfway there.
Now that we have the macro-level explanation of React out of the way, let's point out a few game changers when it comes to the implementation of React itself.
The following sections describe several of the architecture patterns and syntactical candy, adding to the uniqueness of React.
The first thing you'll notice is you're writing a HTML-like syntax within your javascript. If you've used any client-side frameworks in the past, you've probably gotten used to javascript template engines or embedding HTML templates inside script tags on the page.
React goes a step further and turns these snippets of HTML into Components. Instead of nesting raw HTML, you're grouping repeated chunks of HTML into component classes, and writing markup which nests these components inside one another.
Rather than this:
<div class="calendar-component">
<div class="calendar-date-component"> <input type="text" name="month" /> <input type="text" name="day" /> <input type="text" name="year" /> <input type="text" name="time" /> </div>
<div class="calendar-display-component">
<div class="calendar-week-row-1"> ... </div>
<div class="calendar-week-row-2"> ... </div>
<div class="calendar-week-row-3"> ... </div>
<div class="calendar-week-row-4"> ... </div>
</div>
</div>
You're managing something like this:
<CalendarComponent>
<CalendarDateComponent />
<CalendarDisplayComponent />
</CalendarComponent>
Very quickly, this style of Component creation becomes very appealing.
Before React, I had a very loose way of creating components inside the javascript. In many cases, there wasn't a strict sense of where the code for an individual Component lives. A single component would have the markup inside an HTML file, the view was handled in a javascript file, and the state of the component was handled through various DOM bindings happening throughout the entire javascript code.
With React, you're able to keep ALL of that logic within a single component javascript file, keeping all aspects making up a component in one place. The organization and abstraction this facilitates is glorious, and makes automated testing a breeze.
Another area where React has a strict opinion on the way things should be organized is with State.
When thinking about an interface, React says there are two types of data. The first are Properties. Properties are essentially the stored data your interface is displaying. If you're displaying a Todo list, properties would be things like the Todo item name, the description of an item, or the time it was created.
The second type of data is State data. If Properties are storable data within an interface, State is used to maintain the "state" of the interface, as a user interacts with it. Things like opening and closing of a panel, the direction in which a switch is toggled, or if a modal window is shown or not, are all State. The React docs explain State by telling you what it isn't:
Aligning well with the Single Responsiblity Principle, this opinionated separation of the way data is stored and maintained within the interface, makes development much simpler. You're writing independent code to manage each unique type of data, which in implementation, are very different in how they affect the application.
Dataflow is a mechanic which all frameworks seem to handle in different ways. It's a concept older javascript frameworks hadn't quite concerned themselves with, but with the growing complexity of client-side application logic in modern web applications, it becomes much more important to manage.
With frameworks like jQuery and Backbone, preferred dataflow isn't really specified. Some design patterns might imply one method versus another, but at the end of the day it's up to the developer to choose.
Angular is an example of a framework implementing bi-directional dataflow. When the user makes an update within an interface, the update is sent upwards back through the application triggering an update within the data model itself. If the model is updated (through maybe an ajax request, or websocket update), the updates cascade down through the application making requisite updates within the interface itself.
Unidirectional dataflow, the method React implements, is advocated as being more simple than bidirectional. Rather than needing to manage two ways of data movement, you're only managing one. This makes the communication between components, and between your data models, much more streamlined and organized.
With unidirectional dataflow, all a component needs to do is render itself based on the data it's provided. If an update happens to the data, it simply re-renders itself with new set data.
In this example below, you can see how the data passed to the ProfilePic and ProfileLink components are explictly defined as properties of the components themselves. Components don't access data from a random event messangers, or external service provides, they simply access data attached to the properties they are passed. Clean and simple
var Avatar = React.createClass({
render: function() {
return (
<div>
<ProfilePic username={this.props.username} />
<ProfileLink username={this.props.username} />
</div>
);
}
});
Combined with unidirectional data flow, React advocates (but doesn't require) a client-side architecture called Flux.
It's important to note React and Flux are not requiremtnts of one another. Flux can be implemented without React, and React without Flux. Also, Flux is less of a library and more of an architecture pattern. While there is a package of code allowing you to implement Flux, it's more so a set of classes, allowing you to implement the architecture pattern. Confusing, I know, but it will make sense if you take a brief read through the docs.
In this article I won't go into the details of Flux, but in my efforts, I've found the formal Flux architecture a bit much for the projects we're building.
In the work we've done, we've successfully used a combination of BackboneJS' Model and Collection objects, in conjunction with a loose implementation of Flux, to create a lightweight and flexible architecture.
I'll be typing a follow up to this article with more thoughts and code samples on this approach.
Last but not least, I should mention React's opinion on inline styles. While this isn't an absolute requirement for all React projects, React does encourage developers to keep all styles inline, and managed within a component's javascript file.
This approach, detailed in this SpeakerDeck presentation, is a requirement for React Native and I will say that it's certainly an interesting idea. However, on our web based React projects, I still prefer to keep styles within sass/css files themselves.
In the work we're doing, it's much nicer to have the stylistic presentational layer within into it's own set of files. This way, if a designer or someone tasked with updating aesthetic pieces of the app, needs to make an adjustment, they aren't required to understand the complexities of React.
On the projects where we’ve implemented React, each time we're adding a new component, we're adding two files: A javascript file, containing the components markup and interface logic; And, a SASS file, containing the styles for an individual component.
This approach has helped us keep components as maintainable as possible, while also allowing for all members of our team to make updates when necessary.
Now that we've got a few React projects under our belt, I definitely foresee React being a tool we utilize quite often. Again, going back to it's ease of implementation, any time we're building a workflow entailing a moderate amount of user interaction or state management, React would be a great tool to implement.
Because React is simply a View layer, it's not a tool that's too concerning when it comes to long term maintainability. Where the maintainability and scalability comes into play is when we're talking about the Flux architecture pattern, or the other layers supporting React.
While a large chunk of our work does involve interfaces conducive to React, there are certainly instances where we won't be using it. For brochure websites, or other projects not requiring intensive interface development, our normal javascript + jQuery combo will do the trick.
Even on some sites where you need to write object oriented javascript for various small components on the page, React would probably be overkill.
The beauty of React comes from being able to display data, manage state, and reactively adjust when data changes. If your project is not responsible for managing those interface-heavy responsibilities, React isn't necessary.
This article is by no means a complete introduction to React, but hopefully provided a few thoughts on why we're very excited to be using React JS at Authentic F&F.
While React is certainly not for complete beginners, the library itself is very intuitive and will no doubt be useful to a wide array of javascript developers, at all levels of experience.
If you're a javascript developer who finds themselves writing code to help manage an interface, I would highly suggest taking a look at React JS, and pulling up a chair to the cool kids table.
Subscribe here to get our short and sweet monthly newsletter!