Interface from Data: using React to sync updates and offline activity across devices

Rendering views as a function of state makes networked interfaces more intuitive.

Creating a view from a repeatable process: The Montreal Biosphère by Buckminster Fuller (image)

I started using React after learning that, unlike other JavaScript frameworks, it supports server-side rendering. Little did I know that this choice would lead to my enthusiastic discovery of a particular way to build user interfaces.

View as a Function of State

“The core premise for React is that UIs are simply a projection of data into a different form of data.” (React — Basic Theoretical Concepts)

React interfaces are made of components that render views based on the current state of the application. This sounds straightforward, but compare the way many JavaScript apps respond to events by manipulating elements in the browser, while interacting with other elements, and when unlucky, clashing with other events. Consider if you could instead write code to render elements based on the current state, and to change the state based on specific events, while transparently handling browser transitions between different renderings. Developing this way with React feels like an epiphany.

This method of updating UI is essentially the declarative model of HTML — this is a list, these are the items inside this list — reflected in JavaScript. React is not fully declarative, because components can run arbitrary code, such as conditional expressions or loops. But the actual rendering functions are pure: the same data will return the same output. No surprises.

I was figuring out how to use React to show a hidden element in response to a click when I really understood: even toggling element visibility or disabling a button should be handled using data. Don’t manipulate the property of an element in the browser; use a variable to set the property in the first place, then update the variable when necessary. It’s a bit Zen.

Interestingly, in practice, React reminds me of server-side rendering. What is a WordPress template? Some PHP code that renders webpage elements from data. React components? JavaScript code that renders webpage elements from data. When the data changes, you run the same code, rendering the elements again. Incidentally, the way both PHP pages and React components mix markup and logic is decried by purists who advocate separation of concerns in code. React proponents counter that markup is so interwoven with logic in webpages — raise your hand if you’ve ever written an if/else condition in a template — that such divisions end up separating “technologies, not concerns.”

It is easy to go deep into technical or philosophical aspects of React: the Virtual DOM, immutable data, immediate mode graphics, and the functional programming ecosystem. However, I am wary of fixating on specific approaches to writing programs: ultimately, the users of our products don’t care about coding methodologies. That said, if a tool is enjoyable for developers to use, and enables great user interfaces, both of which drive business goals, then adopting it makes sense across the board. React is not (yet!) a monolithic panacea, or consultant-driven industry trend. It’s just an elegant weapon, for a more declarative age.

Syncing

React renders views as a function of state, and Redux maintains state as a function of actions on previous states. When they are used together in an app, UI updates are expressed with surprising clarity. To demonstrate this, I made a React Sync Demo that coordinates devices connected to the demo app. Actions like adding or deleting a comment, typing in the form fields, or clicking a link are mirrored across devices.

React Sync Demo: using React, Redux and WebSockets to sync updates and offline activity across devices

Astute readers may recognize this app as a modified version of the comment box from the React tutorial. Readers with the good taste to have read my articles will know I previously modified the comment box app for a Redux tutorial and then a Universal React tutorial. This time I didn’t write a tutorial, because I wanted this article to be more conceptual, and because the modifications I made to the app are specific to the demonstration instead of being generally instructive.

The demo app uses WebSockets to communicate with the server. Instead of creating special messages or events for the WebSocket, given that Redux actions are JavaScript objects and contain the information needed to update the UI, I just send and receive the Redux action object over the network. (I got the idea from this tutorial).

Offline Activity

I noticed an interesting phenomenon: when interface is derived from data, the state of the interface is readily available as data. Since the view is rendered from a JavaScript object, nothing can change on the screen without first changing a variable. Now, a variable isn’t only a medium of expression, it’s a medium of storage. If portions of your React app keep working while it is offline, you have conveniently built up a transportable data structure of offline activity. On reconnecting, you can send this offline data to the server, which would combine your offline changes with the live server data, and save the resulting combined data. The demo app does exactly that.

This isn’t a comprehensive solution for offline support, of course. But it’s a neat trick, especially useful for flaky mobile connections that fade in and out.

In Practice

Syncing inputs and routes in the demo app is admittedly a gimmick, but clearly expressing UI updates, both within applications and across networks, is increasingly valuable as people use the same apps across multiple devices and environments. If your form inputs are an easily synced object, users can start filling out an order on their phone and complete it at a desktop.

New technologies like HTTP/2 and WebSockets are trending towards low-latency, real time, and push communication, while Service Workers are enabling web apps that support persistence and offline activity. As a greater number of applications transmit streams of data, a UI library based on data transformations can lead to more intuitive code on both the client and server. We have enough complexity to deal with in mediums, devices, and networks; let’s reduce complexity in developing user interfaces.

view = f(state)

A more declarative approach to building interfaces is the way forward.

Further Reading

  • React — Basic Theoretical Concepts: “A description of the conceptual model of React without implementation burden.”
  • Pure UI: “A lot has been written about the merits of React as a framework. Today I’m compelled to write about the benefits of a programming model it enables and its implications to the design and creation workflow."
  • Removing User Interface Complexity, or Why React is Awesome: “I’m mostly concerned with the core problems of data binding and componentizing UIs. After much research and usage of the technologies mentioned above, I found React to provide the best solution.”
  • Pete Hunt: React: Rethinking best practices (youtube): “building views with JavaScript, ‘re-​rendering’ your entire application when your data changes, and a lightweight implementation of the DOM and events.”
  • Nothing new in React and Flux except one thing: “What is it that makes React so innovative and compelling?… The Virtual DOM allows us to convert a mutable retained mode graphics API to an immutable functional immediate mode API.”

Questions or feedback? Let me know in the comments.

I’m currently looking for projects or other opportunities in web development and product management roles. You can get in touch with me on Twitter, LinkedIn or firasd at gmail