[email protected]
Back to About

How We Used React to Build GIF Battle

By


Postlight spends a lot of time chatting and sharing links, and in particular we share a ton of animated GIFs throughout the course of the day. Which led us to wonder: What if we could only talk in GIF images? We’re a group of product managers, programmers, and designers, so in November 2015 we decided to see if we could build a truly GIF-focused, web-based chat app in our spare time. The result was the GIF Battle chat app that we released in January.

We chose to use the React JavaScript library to develop GIF Battle. We wanted to spend some time with React and see how viable it was for client work. It was a roaring success.


What is React?

React, originally developed by Facebook, is a JavaScript library for building user interfaces. It allows developers to build isolated components that describe how their application works.

Isolation is key in React. By isolating one component from another, you avoid a ton of interpendencies. This allows multiple developers to be productive on a codebase. Each developer produces isolated bits of code that are as easy to use as a regular <div> or <span>.

Developer Experience

“User experience” (UX) is a term that should matter to anyone creating software meant to be used by humans. Developer experience is a much less commonly used term, but incredibly important. One developer can make software that is used daily by millions of people. If the developer does not prioritize user experience, he or she can make life horrible (or at least exhausting) for those millions of users. Happy, productive developers who aren’t annoyed are going to build better software. The React ecosystem prioritizes developer experience in a few very noticeable ways:

Hot Loading

Refreshing a webpage is a thing of the past. When the developer saves a file that code is swapped live in the browser thanks to React Transform. So the code you write is always reflected in the interface on screen.

Errors Don’t Just Infest Your App

When you save a file with an error, the app doesn’t silently fail. Instead, it covers the running app with a huge red box—so you don’t miss the fact that your error has stopped the app from running. You solve problems as they crop up.

How It Feels While You Code

One of the big benefits of React is the nearly zero time wasted round-tripping between code and app. Developers can work and see the results of their changes almost instantly. Take a look at this GIF to see how it feels:

Note that this is the second step of a stateful wizard. An opponent has already been selected, and that data is not lost when the code changes while the app is running.

Higher Order Components

We fell in love with higher order components while building GIF Battle. Proposed by Sebastian Markbåge and popularized by Dan Abramov’s article. James Nelson gives wonderfully succinct definition:

Higher order components are JavaScript functions which add functionality to existing component classes. Just as React components let you add functionality to an application, Higher-Order Components let you add functionality to components. You could say they’re components for components.

The use of higher order components in our app followed two use cases, display and data.

Display

GIF Battle is a live, timed, battle. We need to update the UI not just on player action, but also based on the clock. Instead of implementing the logic for a timer in every component, we turned it into a higher order component:

https://gist.github.com/mutewinter/e2fcd172dc15b8f55ecd

Now we can make any part of our interface update automatically with a global clock. PlayerTimer is a component for displaying the amount of time left in a player’s turn. With a single line of code, @updateOnInterval(1), the timer goes from a static number to a ticking clock.

https://gist.github.com/mutewinter/7d2e8a2dfed2a106bcb3


Data

Components define their own data needs using a higher order component. Defining data needs alongside components means that a single file can describe everything a component needs and how it functions. A single location for code also means a single location for bugs. It meant we were able to lock down parts of our application and not worry that they might suddenly break later when a different component is on the page at the same time.

Our MessageList component handles rendering all of the messages in a battle. Here’s the entire definition of its data needs:

https://gist.github.com/mutewinter/2fdd117320b4569e71f9

We also handle rendering error UI in listenToFirebase, ensuring the decorated component doesn’t have to worry about anything but the happy path.

Linting

GIF Battle was a side project. Developers cycled on and off the project regularly. Enforcing code quality without a code overlord to say, “You indented that wrong” could be difficult. Instead, we used ESLint and Stylelint.

Beyond just watching for missing semicolons, ESLint enforced best practices and style.

react/jsx-no-bind is well-explained in ESLint’s documentation.

Stylelint ensures that our CSS is succinct and minimal, no matter which developer writes it.

Alphabetical property ordering helped keep our CSS predictable across all files.

Prototyping

We built at least four versions of GIF Battle, all within the same codebase. We didn’t throw away the code and start over each time. Using React allowed us to build our own abstractions while keeping the logic of our application isolated in components.

When we pivoted from a global, always running timer to a per-player chess timer, we were able to keep almost all of the logic we’d already written. Retaining our existing code was possible due to component isolation and higher order components.

Normally this kind of prototyping would be so costly during the development that you wouldn’t even risk it. Instead, you’d rely on iterating in the design phase. In the case of GIF Battle, that wouldn’t cut it. You can’t really test a global timer in a game in static prototypes. With React we were able to tweak and play and tweak.

Developers and Development

There are tons of libraries for JavaScript now, and there’s a lot of hype about many of them. But rarely does one come along that cares about development experience. Like with any new technology, there’s an uphill climb at first, but with React the payoffs come quickly, maybe because the focus on developer experience has been prioritized. It’s good to use tools that work.


Jeremy Mack is a director of engineering at Postlight. Postlight is a rapidly-growing product shop in New York City that builds mobile and web apps for our clients and for ourselves. We love the web — the real, messy, global web, JavaScript frameworks and all — way more than is healthy or sane. If we can be of service, get in touch.

Story published on Feb 5, 2016.