About the Author:

Map Making with Google Sheets and React

August 17th, 2018

Data visualizations have gotten a lot more popular over the last 5-10 years with the rise of software like D3, Tableau, and infographics. Maps just might be the original data visualization. In fact, maps are so commonplace that we don’t often see them in the same realm as the newer/shinier forms of data visualization. But like other data visualizations, they are just a representation of data (spatial in this case). For almost every web application that works with spatial data, maps are essential.

There are a variety of libraries for building maps in React-based applications. This tutorial will focus on building a simple google map using React, Google Sheets, and the very powerful (and well-maintained) google-map-react library.

In my previous article, I covered how to make a simple React app that pulled data in from a Google Sheet using the sheets API. We’ll be building upon that to make a simple map using that same data.

Let’s Build a Map of Sweet Views

A little backstory on the demo app we’ll build: the San Francisco Bay Area is full of hills. On some of these hills, you can find public spaces with incredible views of the ocean, city, bay, and various neighborhoods. After having your head in a computer all day, there’s no better way to zoom out, admire your gorgeous and expensive city, and think about how small you are. But if you just moved to the area, you might not know where to find these great views. Hence the need for a map!

Let’s help people get to places like this

Here are some of my favorite views in the bay area and the data we’ll be using for this app:

idnamelatlng
1Grandview Park37.7564084-122.4717396
2Hawk Hill37.8254957-122.4995417
3Grizzly Peak37.8822385-122.2336546
4Bernal Heights37.7431498-122.4152257
5Tank Hill37.7599703-122.4477785

Install Dependencies and Set Required Values

To add a map to our original project (clone here) , we first need to install google-map-react:

$ yarn add google-map-react

With that done, let’s create a MapAndMarkers component that we’ll call in our main App component and pass some props to.

Let’s first call the component in our main App.js file (and we’ll build it after).

import MapAndMarkers from './MapAndMarkers.js'

The GoogleMapReact component (from google-map-react) has a few required props in order to make a map. Two of these props are center and zoom. These are, logically, the minimum for having a map. The map needs to know which tiles (map images) to load and center on and how far to zoom in.

Let’s have these live in our parent App’s state. We can change these state values later (with user events) to have our components re-render. So state will now look like this in the component:

this.state = {
     items:[],
     center: { lat: 37.8254957, lng: -122.4995417 },
     zoom: 10,
    };

Google maps zoom values must range between 1 (the whole world) and 20 (down to specific buildings). These center coordinates are located roughly in the San Francisco Bay. This zoom level of 10 shows the general Bay Area. Now pass these to the MapAndMarkers component:

<MapAndMarkers markers={this.state.items} zoom={this.state.zoom} center={this.state.center} />

Create MapAndMarkers Component

We are now going to create a very simple MapAndMarkers component. I’ll put comments in the code to explain what is happening:

import React, { Component } from "react";
import GoogleMapReact from "google-map-react"; // This is the primary map parent component

/* A very very simple map marker */
const Marker = ({ name }) =>
  <div>
    {name}
  </div>;

export default class MapAndMarkers extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { markers } = this.props; // Destructuring our props to get the google sheets data

    // map over the array of markers to create a set of mapmarkers for our map to display. Map markers, as you can imagine, need to have lat and lng props in order for the parent map to know where to put them.
    let mapmarkers = markers.map((marker, index) => {
      return (
        <Marker
          key={marker.id}
          lat={marker.lat}
          lng={marker.lng}
          name={marker.name}
        />
      );
    });
    /*
Call the GoogleMapReact component and pass it the api keys and google maps version in the bootstrapURLKeys prop.
Pass it the center and zoom from props.
The array of mapmarkers is given to the GoogleMapReact component (as its child) to be rendered on the map
*/
    return (
      <div style={{ height: "100vh" }}>
        <GoogleMapReact
          bootstrapURLKeys={{
            key: "yourapikey",
            // get a key here: https://developers.google.com/maps/documentation/javascript/get-api-key
            v: "3.32"
          }}
          center={this.props.center}
          zoom={this.props.zoom}
        >
          {mapmarkers} // array of map marker divs
        </GoogleMapReact>
      </div>
    );
  }
}

This component will render a map and markers that looks something like this:

Pretty ugly, right? The only reason I did this was to show that google-map-react can render any component on a map. It can be a map pin/marker, a custom animation, shapes, or just plain text like above. This library gives the React developer a lot of freedom to make maps in a component-driven way. We are simply rendering components on a map. Other mapping libraries (e.g. tomchentw/react-google-maps) might give you more HOCs and built-in methods to play with, but I found they didn’t follow the React small-composable-components paradigm as much.

Make Prettier Map Markers

Let’s make our map markers more marker-like with some icons. Feather icons is a well-maintained and lightweight icon library. React-feather offers feather icons as components. Let’s use that.

$ yarn add react-feather

We import the feather map pin icon simply enough:

$ import { MapPin } from 'react-feather';

And change our marker to this:

const Marker = ({name}) => (
   <div><MapPin />{name}</div>
);

Getting warmer:

How About a Tooltip?

A tooltip would go a long ways toward making these markers look a bit more map-like.

There are dozens of React tooltip libraries out there. They vary greatly in terms of their APIs and maintenance. As with any library, I recommend some caution and research before adding a tooltip library to your project. There are few things more frustrating than finding your issue is the same issue that many other have (and the maintainer hasn’t accepted pull requests in many months). Rc-tooltip is a well-maintained tooltip library and has a straightforward and robust API.

Implementing the tooltip is quite straightforward:

$ yarn add react-tooltip

 

import Tooltip from "rc-tooltip";<br>
import '../node_modules/rc-tooltip/assets/bootstrap.css';

// basic integration of Tooltip with the previous Marker

const Marker = ({ name }) =>
  <div style={{ height: "50px", width: "50px" }}>
    <Tooltip
      placement="top" // You can choose whichever side you want it to show on
      animation="zoom" // A smooth zoomy animation when it opens
      overlay={ 
        <span>
          {name} // What shows up in the tooltip
        </span>
      }
    >
      <span> <MapPin /></span> // Hovering on the MapPin will cue the pop up
    </Tooltip>
   
  </div>;

This gives us clean, animated tooltips for our map icons.

We’ve now covered the basics of rendering map points on a Google map and giving them cute icons and tooltips. There’s so much more we can do, of course. Future tutorials will delve into responding to user events like hovering on the map and opening and closing our tooltips using state and props.

The code for this tutorial is here: https://github.com/kpennell/google-sheets-map

About the Author:

25 Public React Repos/Apps to Inspire Your Next Project (part 1)

August 10th, 2018

In the last couple of years, React has risen to become a massively popular JavaScript library and developer ecosystem. There are tens of thousands of software projects that use React and many of them are publicly available on Github. It’s fun and enlightening to check out what other developers have made with React and dig into how they write code.

But since you might not want to spend your free time combing through public React-using projects (or maybe, you might…), I went and found 12 great ones (for part 1) for you to check out. I hope these inspire you to try new design patterns, new libraries, or simply just build new things.

Note: Some but not all are MIT licensed.

My criteria for searching was they be somewhat interesting, have a functioning demo, and be updated after mid 2017.

Automattic/wp-calypso (demo)

Calypso is a project by Automattic, the creators of WordPress. WordPress is a famously PHP using project so this was Automattic’s fun foray into the JavaScript and React worlds. They built a very helpful dashboard for WordPress power users to manage their projects.

honeypotio/techmap (demo)

This is an incredibly clever map of London tech companies superimposed on a subway map and made by jobsite Honeypot. It appears to be built only in React and let you filter with the sidebar as well as the map. You can filter based off of technology or industry. This is a great project for learning filtering and routing from events on a map.

shoumma/Book-of-Spices (Free Android app in Play Store)

As someone who cooks a lot of Thai and Indian food (and would like to learn more cuisines), this is a super cool app for learning all about different world spices. This projects uses react-native-animatable and react-native-swiper to create smooth animations and swiping through the content. This would be a great project to model after if you’re taking on a static content browsing app using React Native.

ng-hai/simple-trello (demo)

This a well-organized React + Firebase Trello Clone. I’m impressed how much it looks like Trello. This project uses Brad Frost’s atoms, molecules, and organisms method for organizing components.

tigranpetrossian/hacker-news-redesigned (demo)

This is a React + GraphQL + Server-side rendering based Hacker News redesign. The components and GraphQL queries seem to be well-organized. I almost like this interface better than the default.

chienkira/musyc (demo)

This is an elegant Spotify player built with React, Redux and Semantic-ui. It uses react-soundplayer to play the mp3s. This is a good project for learning to use the Spotify API (including reading user data). As much as I love Bootstrap and Material-ui, Semantic-ui is a breath of fresh air.

aholachek/react-stripe-menu (demo)

I’d never seen such an elegant menu until I saw this one. This excellent code is accompanied by a thorough tutorial on CSS tricks. Now there’s no excuse for a janky mega menu!

imandyie/react-native-airbnb-clone (native app / no demo)

Here’s a very accurate looking AirBnB mobile clone using React Native, Redux, react-native-vector-icons, react-navigation, redux-thunk, and redux-logger. This would be a great project for anyone needing to make an elegant travel app or needing to learn the advanced parts of Redux.

browniefed/pdxlivebus (demo)


This is likely my favorite of bunch. Click the demo! Watch Portland’s busses move in real-time through the app. This is one of those ‘where have you been all my life?’ types of apps. The map is built using Leaflet and and react-native-maps. This an excellent example for anyone needing to build realtime cross-platform apps using JavaScript.

chvin/react-tetris (demo)

This an awesome Tetris clone built using Redux, Immutable.js, PostCSS, Less, and many other libraries. It uses localStorage to save your game play. There is a ton of complexity and tooling that went into making this all look so simple and like real Tetris.

rwieruch/favesound-mobx (Demo)

Berlin-based developer Robin Wieruch has made quite a name for himself with massive and thorough tutorials on React, Redux, Mobx, Firebase and GraphQL. His tutorials will definitely send you down an educational rabbit hole. This set of tutorials shows how he converts a Redux soundcloud player to Mobx. This is invaluable for any developer considering either technology or needing to learn about state management

 

rafaesc/reactube-client (demo)

It’s no surprise that a lot of the projects I’ve mentioned have used Redux. But this simple Youtube clone uses the newer React context for managing state. This projects also uses styled components and TypeScript. This code base would be helpful for anyone needing a simple example of these technologies tied together in action.

 

I hope these projects send you down a fun rabbit hole of architecture patterns, library discovery, and dreaming up your next project.

 

About the Author:

The Simple Stack: A Primer on Using React + Google Sheets API

August 3rd, 2018

Data-driven web applications are invaluable for all sorts of people and businesses. But updating or changing data in a relational or NoSQL database is not something most non-programmers can do. Wouldn’t it be nice if we could power simple applications using a data source that many non-technical people are comfortable with? Thankfully, there’s Google Sheets and the increasingly well-documented v4 of its API.

Unlike a JSON or SQL database, a Google Sheet can be shared, edited, consumed, calculated with, and commented on by nearly anyone with a web browser. This makes google spreadsheet data (consumed via an API) a great data source for simple and low traffic web apps. This article will show you the basics for GETting data from a google spreadsheet using version 4 of their API and consuming that data using a simple React app.

This is obviously not the first attempt at using a spreadsheet as a backend. However, many of the tutorials or existings solutions were outdated (as of mid 2018), proprietary or used Angular/jQuery to consume the data. This tutorial will simplify the process, use the API directly, leverage v4 of the API, and use React to consume/use the data.

First Setup the API

Here’s what I did to make some google spreadsheet data consumable via their API.

1. Put the following data into a fresh google spreadsheet:

idnamelatlng
1Grandview Park37.7564084-122.4717396
2Hawk Hill37.8254957-122.4995417
3Grizzly Peak37.8822385-122.2336546
4Bernal Heights37.7431498-122.4152257
5Tank Hill37.7599703-122.4477785

2. Share the sheet so anyone can view it:

3. Use Google’s API Explorer Tools to construct a JSON request URL.

The API method we’re calling is batchGet. batchGet is used for returning “one or more ranges of values from a spreadsheet. The caller must specify the spreadsheet ID and one or more ranges.” It’s the primary method we use to GET data.

4. Fill out the form in the batchGet explorer:

Your spreadsheet id is the long string after ‘/spreadsheets/d/’ and before ‘/edit#gid=0’. Mine is 1mpFIiSlkqU0BQml5la3nEwkmj3QJUR8SvkaCHJmm6zk. Your ‘ranges’ is Sheet1 (unless you’ve changed it). Go with ROWS for the majorDimension. For the authentication, go with API key. Google will give you a fake one in this demo.

You should see the data now once you run it.

5. Go get a real API key

You’ll need an actual API key to get the data from your sheets. This can be done in the google console here.

6. Construct and try your real JSON API url.

Mine looks like this : https://sheets.googleapis.com/v4/spreadsheets/1mpFIiLlkqU0BQmn5pa3nEwkmy3QJUR8SvkaCHJmm6zk/values:batchGet?ranges=Sheet1&majorDimension=ROWS&key=AIzaSyBNTDOtaFrsIMaKsIJ_E3CxKaTwf0tCaW8

I try this in my browser and get JSON. It looks something like this:

That’s all cool and all. Actual JSON from a spreadsheet. But…you’ll notice this is odd data. values is an array with an array for each row. Hmmmm…this will be odd to work with. I’d prefer an array of objects. We shall do this next within our basic React app.

Creating a Basic List with our spreadsheet JSON

For this app, we’re just going to retrieve some data and display it in a list. In future articles, we will do more interesting stuff with this data.

Scaffold a basic React app

I use create-react-app to get the basic app setup quickly.

$ create-react-app sheetsdemo
$ cd sheetsdemo

We’ll do everything from directly within App.js, which create-react-app so graciously gives us. This is not supposed to be great architecture, rather just a display of the concepts.

  1. Setup an empty array in this.state
constructor(){
    super();

    this.state = {
     items:[]
    };

  }
  1. Fetch the JSON data from within componentDidMount

componentDidMount is the most commonly used React lifecycle method for fetching data.

I first assign my JSON url to a variable:

const API = 'https://sheets.googleapis.com/v4/spreadsheets/1mpFIiLlkqU0BQmn5pa3nEwkmy3QJUR8SvkaCHJmm6zk/values:batchGet?ranges=Sheet1&majorDimension=ROWS&key=AIzaSyBNTDOtaFrsIMaKsIJ_E3CxKaTwf0tCaW8'

Then, I use the componentDidMount lifestyle method to call the API using fetch.

  componentDidMount(){

     fetch(API).then(response => response.json()).then(data => {
      let batchRowValues = data.valueRanges[0].values;

      const rows = [];
      for (let i = 1; i < batchRowValues.length; i++) {
        let rowObject = {};
        for (let j = 0; j < batchRowValues[i].length; j++) {
          rowObject[batchRowValues[0][j]] = batchRowValues[i][j];
        }
        rows.push(rowObject);
      }

        this.setState({ items: rows });
        console.log(this.state.items);
    });

  }

You can see the fetch promise in use at the top. But then what are those two loops after that? With those two for loops, I’m able to convert my values array of individual row arrays into an array of objects for each row. My console now logs the array of objects.

[
  {
    "id": "1",
    "name": "Grandview Park",
    "lat": "37.7564084",
    "lng": "-122.4717396"
  },
  {
    "id": "2",
    "name": "Hawk Hill",
    "lat": "37.8254957",
    "lng": "-122.4995417"
  },
….

4. Loop/map over the array of objects to create a simple list.

JavaScript Array.prototype.map() is the best for this and very commonly used for repeating elements in React. I change my render method to the following to get a very simple list:

  render() {
    const listItems = this.state.items.map((item) =>
    <li>{item.name} at Latitute {item.lat} and Longitude {item.lng} </li>
  );

    return (
      <div>
         <ul>{listItems}</ul>
      </div>
    );
  }

And get the following result:

Now this app is definitely not anything super impressive on the display side. But stop for a second and admire that you’re serving up data from a google spreadsheet directly into a React app. If you change anything in the spreadsheet and refresh the React app, the changes are immediately propagated. It does not get much simpler for a data driven web app.

Upcoming tutorials will show how we can do much more interesting things with this data, like making a map.

Github repo of final code: https://github.com/kpennell/sheetsdemo

About the Author:

How to Build a Simple Chat App with React Native and Firebase

November 30th, 2017

Nick is a mobile developer with wide experience in building iOS and Android applications at RubyGarage. He enjoys researching tech topics and sharing his knowledge with other developers.

In mobile development, cross-platform applications are appreciated for their short development cycle, low cost, and quick time to market in comparison with native apps.

One popular framework that enables developers to build hybrid mobile apps is React Native. React Native was created by Facebook developers during a hackathon back in 2013. Since then, the framework has become a core technology for numerous mobile applications including Instagram, Skype, Tesla, Airbnb, and Walmart. (more…)

About the Author:

The Journey from Vue to MobX

August 25th, 2017

I recently began using React with MobX at my new company. Having used Vue with VueX at my previous job, I immediately noticed congruence between the two patterns. What I had become so fond of with Vue after being a long time React/Redux user, I found baked into the MobX philosophy.

I’ve seen a lot of people adopting Vue this year. Sarah Drasner’s fantastic series on CSSTricks probably played a big part in that migration. However I believe we JS developers live in a meritocracy (for the most part) and I mainly credit this diaspora to a few things:

  • event handling
  • multiple rendering options (templates or render functions with JSX)
  • truly reactive components

This last point is the kicker. Vue has reactivity baked directly into its components. I think this simplicity and thoughtful architecture is the main reason for all the hype and it’s why I took such a liking to Vue. This is not a novel concept, as we’ve seen native reactivity in frameworks like Ember and Knockout before, but its elegance in Vue makes it superior.

This piece is not meant to be a comparison of React + MobX and Vue + VueX. This post from the Vue docs that topped HackerNews last week does a fair job at this. I earnestly believe both solutions are great and have their use cases. This this post aims to do is introduce MobX concepts from the perspective of someone who loves Vue reactivity.

Enter MobX

When I first learned that I was would be moving to Vue professionally, I privately grieved. There were many things I initially missed: a large developer community, dedicated support from a tech powerhouse in Facebook; however, the thought of going back to my days of Redux boilerplates and a more verbose state management solution was less than enticing.

In fact, I came to appreciate thinking in “the Vue way” so much so that I expressed that same sadness when I learned that I would be moving back to React. That is until I learned that my new team was using MobX.

The state management pattern that MobX brings to a view framework like React might seem so similar to Vue that at first you might ask yourself…

Evan You tweet on MobX

Although humorous (and somewhat true), I see this as a mostly straw man argument. MobX does not claim to supplant Vue and its ideology. What it does offer is a less-opinionated and more robust alternative to the reactive data management pattern built into Vue.

Travel Log

In this section, I want to demonstrate how we might write some code in Vue, followed by its implementation with React + MobX. As a basis for our comparison, let’s use a tiny app I built that lists several places around the world and let’s us mark the locations of the ones we’ve visited.

An app like this requires the use of state to manage our currently selected location and the list of places we’ve visited. I’ve implemented the app three different ways: once using React local state, once more in Vue, and one last time with React + MobX. We’ll go through the general paradigms of local state management using the logic contained in these apps.

data => observable

State is essential to any complex application. While React provides an option for managing local state, it requires usage of the setState function and is limited to a single object. Vue introduces data, instead, as a mechanism for declaring reactive local variables.

In our app, we use data to keep track of the cities we’ve visited, our currently selected city, and a few variables we need to manage the alert.

data: function() {
return {
cities: cities,
selectedCityId: null,
visited: {},
alert: false,
clearAlert: null
}
},

Just like that, this data (i.e. your state) is now reactive. You can update these variables from any JS within the Vue component and Vue will re-render the component if necessary. This removes the need to use setState — or any other function for that matter — to update local state.

MobX takes a similar approach, but instead of a singular data object your reactive variables are wrapped in observables.

cities = cities;
@observable selectedCityId;
@observable visited = {};
@observable showAlert = false;
@observable clearAlert;

By wrapping your component in an observer from the mobx-react connector library, the component becomes reactive to mutations of these variables. Like Vue, the component will now update when they are used in the render function of the component.

computed => computed

The addition of computed variables begins to shine light on the advantage of this approach. When only using local state, we are left to compute certain variables every time the component renders. Computed variables allows us to compute a new value every time a dependent variable changes, caching that value until one of the dependencies changes.

computed: {
selectedCity() {
return this.cities.find(city => city.id === this.selectedCityId);
},
sortedCities() {
return this.cities.sort((a, b) => a.name > b.name ? 1 : -1);
}
},

In our app, Vue computes an alphabetically sorted version of the cities array. This is preferred over computing it every time we render, as this array does not actually change throughout the lifecycle of our component. As these transformations become more expensive, this feature becomes crucial for building a performant PWA.

MobX gives us the same ability with its computed object.

extendObservable(this, {
cities,
sortedCities: computed(function() {
return this.cities.sort((a, b) => a.name > b.name ? 1 : -1);
}),
selectedCity: computed(function() {
return this.cities.find(city => city.id === this.selectedCityId);
})
})

The only difference here is syntax. All the spoils remain the same.

method => action

One major difference between Vue and React is the makeup of the components themselves. Vue eschews ES6 classes in favor of custom components with specific options (i.e. data, computed, etc). This gives it tight control over where the user can control certain behavior and certainly brings a sense of organization to each component. One place where this is evident are the method functions. These are the only functions capable of updating local state that you can explicitly invoke from within your template (for the sake of this discussion, that is).

methods: {
selectCity(cityId) {
this.selectedCityId = cityId;
},

toggleCity(cityId) {
if (this.visited[cityId]) {
const { [cityId]: city, ...rest } = this.visited;
this.visited = rest;
} else {
this.visited = { ...this.visited, [cityId]: true };
}
}
}

Nothing too crazy here. We select a city and update the selectedCityId accordingly. We can, of course, write this logic inline in our click handlers, but methods help us organize our code and keep it DRY.

Lo and behold, the MobX equivalent is not too far off with actions.

@action selectCity(cityId) {
this.selectedCityId = cityId;
}

@action toggleCity(cityId) {
if (this.visited[cityId]) {
const { [cityId]: city, ...rest } = this.visited;
this.visited = rest;
} else {
this.visited = { ...this.visited, [cityId]: true };
}
}

There really isn’t much of a difference here at the base level. In fact, you don’t even need to use actions to update local observables. You can simply update your observables in regular functions, as long as strict mode is not enabled. Where actions become beneficial is in their inherent performance boost, described in the docs as such:

…actions will batch mutations and only notify computed values and reactions after the (outer most) action has finished. This makes sure intermediate or incomplete values produced during an action are not visible to the rest of the application until the action has finished.

With the addition of runInAction, this makes writing complex state-updating functions easier by simplifying the predictability of your component’s state.

watch => reaction

The final piece to any complex component’s state management suite is its need for imperative code. In our app, for example, we want to display an alert banner every time the user updates their log. When using only React’s local state, we are forced to explicitly tell the banner to appear with the showAlert function. Acting strictly as a view layer, React’s goal is not to emit side effects, so it only makes sense that local state does not provide us with optimal ways to produce them. However, any front end developer knows that these are unavoidable when building a robust UI. If only there was a way for us to react to specific state updates…

Thinking

As you may have expected, Vue gives us the handy concept of watch to do just that.

watch: {
visited() {
if (this.clearAlert) {
clearTimeout(this.clearAlert);
}

this.clearAlert = setTimeout(() => {
this.alert = false;
}, 3000);
this.alert = true;
}
},

This piece of code essentially says that every time our visited object changes, we run a function in response. I love this pattern because it no longer requires us to think about when we need to display our alert. Instead, our code just knows that every time we update our log, the banner should display. We are even given a deep option for instructing Vue to watch for mutations deep within our state objects, meaning immutability is not even required for this functionality.

Not surprisingly, MobX offers almost identical functionality with reactions.

const updatedLog = reaction(
()=> this.visited,
() => {
if (this.clearAlert) {
clearTimeout(this.clearAlert)
}

this.clearAlert = setTimeout(() => {
this.showAlert = false;
}, 3000)
this.showAlert = true
}
);

Admittedly, it’s not as clear what is going on here at first glance, so let’s break it down.

A reaction takes two functions as arguments. The first instructs what state variables to watch, while the second contains the code to run when one of those values mutates.

While Vue offers simplicity when it comes to imperative code, MobX rebuttals with power. Reactions are capable of listening to multiple observables at once and only reacting a single time to one mutation, something I always found difficult to work around with watch. MobX also offers a suite of tools that give you more fine-grained control for running imperative code. autorun will simply run when any of its dependencies change, while when replaces the first function with a predicate, only running the latter if the former returns true. This can all be achieved in some fashion with reaction, but these helper functions work to make your state…dare I say it…predictable.

The Verdict

It’s an unequivocal tie!

In all seriousness, both of these patterns are great and provide similar mechanisms for performing the same goals. This piece was simply meant to enlighten developers on the parallels between both libraries. I really do like to use them both in different situations.

However, I would be remiss if I didn’t provide a short (possibly subjective) list of where I think each approach stands out:

MobX Wins

  1. ES7 & Beyond: MobX takes full advantage of recent additions to the language, most blatantly classes and decorators. These are newer concepts to JS, but they provide tried and true patterns that have existed in other languages like Python for eons. Best of all, they are not required, so you can easily use MobX without them.
  2. Predictability: Vue does a great job at this, but I think MobX wins out here. MobX builds out an insanely complex dependency graph behind the scenes that runs all your reactive code synchronously. This is crucial for debugging and actually understanding what the hell is going on in your code!
  3. Extensibility: MobX just works in its own right, so you can use it in just about any context you’d like. Vue’s clean syntax comes at the cost of tightly-coupling your source code with a particular framework. So far I’ve only used it with React projects, but it can just as easily be used in Preact, Inferno, and other rising stars.

Vue Wins

  1. Modifiers: In addition to the basic actions, Vue provides event modifiers and other niceties for writing clean code. It’s a clear indicator to the thought that went in to making this an approachable framework for developers and it speaks to the relevancy of directives.
  2. Documentation: Vue definitely excels here. The documentation is succinct, well-organized, and in-depth in the right areas. Again, this shines a light on the delightful developer experience Vue seeks to provide.
  3. Organization: This can go either way, but as someone obsessed with linting and prettier, Vue brings a very understandable pattern to your development workflow. Everything is where it needs to be, making code handoffs and reviews a more seamless process for a collaborative team.
  4. Clean DOM: For all the benefits of decorators, inject and observer (from mobx-react) do muddy up the DOM with extraneous wrapper components. This becomes frustrating during debugging using the React dev tools and looking for your actual component among the redwood of a tree. Vue keeps the DOM nice and tidy by only rendering your custom components.

Conclusion

My hope for this post was that you got a basic understanding of the similarities between MobX and Vue for managing local state. Both libraries have done a fantastic job of identifying pain points experience by UI developers in recent years and building pragmatic tools to address them. These paradigms can solve many higher-order problems, as well: managing global state with VueX and MobX, handling streams, and proxies.

Feel free to reach out with any questions/comments via the issues of the vue-mobx repo I made containing this post’s code. Go forth and explore the possibilities!

Additional Resources

About the Author:

Using Horizon/RethinkDB with React

August 9th, 2017

Horizon is an open source Backend as a Service (BaaS) that allows developers to easily build data-driven web and mobile applications. Horizon, which is built on RethinkDB and by the RethinkDB team, facilitates common application development tasks like backend setup, real-time data transfer, security and scalability. Horizon can be run locally, on a private server or in the cloud.

This tutorial will give you an introduction to Horizon and RethinkDB while also showing you how to build a simple app with Horizon and React. This will give you a simple and scalable architecture for building your own much more complex apps.

A Quick Note About the State of Horizon/RethinkDB

On October 5th 2016, the company behind RethinkDB announced it would be shut down. This left many users believing the entire project was being cancelled and shuttered. In actuality, RethinkDb and Horizon became fully open source and community driven. On February 6th 2017, the Cloud Native Computing Foundation (CNCF) purchased the rights to the RethinkDB source code and contributed it to the Linux Foundation. This gave the project the necessary support to keep the project alive and facilitate its continuous development.

Horizon + React = Awesome Combo

Horizon and React is a pair made in heaven for developers. Horizon takes charge of all the backend complexities and React facilitates building a modular, reactive frontend. Horizon handles the distribution of data in real-time while React keeps the clients updated. Everything scales and everything has high performance and low latency.

When there is a change in the app’s state, ReactJS will efficiently redraw the necessary components by diffing between the virtual DOM and the existing DOM (and making only the required changes). Horizon notifies all subscribed clients when there is a data update, so they can either download the data again or simply apply the change into its local copy when the original data is too large to fully reload on each change. Together, Horizon and React allow for a simple way to build real-time data-driven applications.

Building a ‘ToBring’ App

To demonstrate how they work together, we’ll build a ‘ToBring’ app (not another another ToDo!). This application will track a list of items we need for a party. This app will allow users to add items in a section that we will call “We need list” or move them to another list called “We have list” and add the name of the user who will bring the item.

To see all the code for this demo, check out this repo.

To keep the setup simple, we’ll use create-react-app. To start the React part of the application, first install create-react-app with the command

npm install -g create-react-app

Then you’ll need to initialize a new app with the commands

create-react-app party_checklist

and

an npm install/start

Once ready, it should launch on your browser with the address http://localhost:3000/ and will auto-reload every time you change the source code.

React is all about components. The main component of our app will have three sub-components: one to add a new item, one to hold the “we need list” and another to hold the “we have list”. Here’s a quick visual of how these components will fit together.

We will need to know the user’s name for keeping track of what they bring. Let’s put a simple input to get the name of the active user into the main component.

If you are wondering, Horizon does include options to authenticate, add permissions and even Transport Layer Security to our app, but that is beyond the scope of this tutorial.

Here’s how we’ll code up the name input:

app.js

import React, { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // A holder for the user name
      user : '',
    };
    // A binding to call updateUser without the () suffix
    this.updateUser = this.updateUser.bind(this);
  }

  render() {
    return (
      <div
        className= 'app'>
        <h1>Party Checklist</h1>
        <p>I am:</p>
        <input
          value = {this.state.user}
          onChange = {this.updateUser} />
      </div>
    );
  }

  // A method to update the state in response to a synthetic event
  updateUser(e) {
    this.setState({user: e.target.value});
  }
}

It is important to remember how we use the constructor to hold the state and also to create bindings to expose methods, without it “this” will return “undefined” when the method is actually called. This is how React handles events, also notice how “updateUser” has a parameter called “e”, this is called a synthetic event.

Now let’s add the NewItem component:

app.js

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user : '',
    };
    this.updateUser = this.updateUser.bind(this);
  }

  render() {
    return (
      <div
        className= 'app'>
        <h1>Party Checklist</h1>
        <p>I am:</p>
        <input
          value = {this.state.user}
          onChange = {this.updateUser} />
        <NewItem />
      </div>
    );
  }

  updateUser(e) {
    this.setState({user: e.target.value});
  }
}

class NewItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      item  : '',
    };
    this.updateItem = this.updateItem.bind(this);
  }
  render() {
    return (
      <div>
        <p>Add to need list:</p>
        <form>
          <input
            value = {this.state.item}
            onChange = {this.updateItem} />
        </form>
      </div>
    );
  }

  updateItem(e) {
    this.setState({item: e.target.value});
  }
}

JSX allows you import the “NewItem” component into “App” similar to custom web components on HTML.

Now let’s make a component for the WeNeedList, notice how it was an “items” list in its properties, this means the value will be passed when it is declared inside another component. When dealing with lists in React, you can use a simple map method.

app.js

class WeNeedList extends React.Component {
  render() {
    return (
      <div>
        <h2>We need...</h2>
        {this.props.items.map(item => (
          <div
            className= 'row'>
            <button
              className= 'remove'>
              x
            </button>
            {item.description}
            <button
              className= 'add'>
              +
            </button>
          </div>
        ))}
      </div>
    );
  }
}

Now lets add “WeNeedList” to “App”.

app.js

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      weNeedList : [],
      user : '',
    };
    this.updateUser = this.updateUser.bind(this);
  }

  render() {
    return (
      <div
        className= 'app'>
        <h1>Party Checklist</h1>
        <p>I am:</p>
        <input
          value = {this.state.user}
          onChange = {this.updateUser} />
        <NewItem />
        <WeNeedList
          items = {this.state.weNeedList}
          user = {this.state.user} />
      </div>
    );
  }

  updateUser(e) {
    this.setState({user: e.target.value});
  }
}

See how “App”will hold the state of the list and will pass it to “WeNeedList” as parameters. Inside “WeNeedList” we can read this values from props.

And finally we need to make a WeHaveList component:

app.js

class WeHaveList extends React.Component {
  render() {
    return (
      <div>
        <h2>We have...</h2>
        {this.props.items.map(item => (
          <div
            className= 'row'
            key = {item.id}>
            <button
              className= 'cancel'>
              x
            </button>
            {item.description} from {item.user}
          </div>
        ))}
      </div>
    );
  }
}

And also add it to the “App” component:

app.js

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      weNeedList : [],
      weHaveList : [],
      user : '',
    };
    this.updateUser = this.updateUser.bind(this);
  }

  render() {
    return (
      <div
        className= 'app'>
        <h1>Party Checklist</h1>
        <p>I am:</p>
        <input
          value = {this.state.user}
          onChange = {this.updateUser} />
        <NewItem />
        <WeNeedList
          items = {this.state.weNeedList}
          user = {this.state.user} />
        <WeHaveList
          items = {this.state.weHaveList} />
      </div>
    );
  }

  updateUser(e) {
    this.setState({user: e.target.value});
  }
}

Now the core of our app is complete! But it doesn’t do anything yet, for that, we need to add Horizon and create a few methods inside our components.

To install Horizon in your machine, simply run the command npm install -g horizon.

Horizon, like create-react-app, automatically initializes everything. You only need to provide the name of the app you want to create with the command hz init party_checklist; it is important that you run this from the same place from where you created the app, so it will just add new files to the project instead of creating a new one. You must always start with React and then add Horizon.

Horizon needs RethinkDB to work. Before launching your Horizon server, make sure you have RethinkDB running on your machine. Refer to the official documentation for detailed instructions on how to run it on your system. The simplest way for Mac users is to use Homebrew to install it.

Now let’s configure Horizon to look for RethinkDB in your local machine. To do so, go to .hz => config.toml and replace it with the following:

bind = [ "localhost" ]
port = 8181

connect = "localhost:28015"
start_rethinkdb = false

To launch your Horizon server locally, go the folder with your project and run hz serve –dev, this will start your local Horizon server on port 8181. Note that you always need to keep one instance running React and another running Horizon while you are developing.

Before hitting the code, let’s learn a few basic Horizon concepts:

Horizon groups data into horizon collections and each collection is backed by a RethinkDB table. All documents inside a collection are identified by a unique key stored in the id field.

Horizon provides a very simple yet powerful API that helps you handle the following aspects:

In this tutorial, we will be focusing on the first two, DB connection and data collections.

ReactJS is designed to use an unidirectional data flow, so the data always flow from the DB into the parts of the UI that represents it. You can stream data right into its specific component or stream many into the parent and then your pass it down via component props.

Here’s a visual to help you make sense of the data flow in this app:

Note that any change in the data is sent from one React client into Horizon and Horizon sends it back to all React apps so they can update their view, this flow makes sure that all clients are always watching the same without inconsistencies. Also note that the data always flows in one direction between Horizon and React.

Let’s add the Horizon client library into our app. First run npm install @horizon/client to get the horizon client installed locally and make an instance of the client holding a connection to our local server in app.js.

app.js

import Horizon from '@horizon/client';
const horizon = new Horizon({host: 'localhost:8181'});

Now let’s configure React to open a connection with the Horizon server right after everything has loaded correctly using the componentDidMount() lifecycle method. We will include some watchers to log when the connection to Horizon is ready and when it gets disconnected.

app.js

class App extends Component {

  // ...

  componentDidMount(){
    horizon.connect();

    horizon
      .onReady()
        .subscribe(() =>
          console.info('Connected to Horizon server'));

    horizon
      .onDisconnected()
        .subscribe(() =>
          console.info('Disconnected from Horizon server'));
  }
}

Remember how we talked about collections in Horizon? Our app will use two Horizon collections, one for the “we need list” and other for the “we have list”. Let’s store a reference to them at the top of app.js.

app.js

import Horizon from '@horizon/client';

const horizon = new Horizon({host: 'localhost:8181'});
const weNeedList_collection = horizon('weNeedList');
const weHaveList_collection = horizon('weHaveList');

Horizon makes it very easy to watch and apply for changes in real time, you can even add custom logic and subscribe to a feed of changes. A common practice is to use the timestamp of each object as its ID and request the collection sorted by the ID, so they will always come in chronological order. Let’s do that for both collections.

app.js

class App extends Component {

  // ...

  componentDidMount(){
    horizon.connect();

    // ...

    weNeedList_collection
      .order('id')
        .watch()
          .subscribe(allItems =>
            this.setState({weNeedList: allItems}),
            error => console.error(error));

    weHaveList_collection
      .order('id')
        .watch()
          .subscribe(allItems =>
            this.setState({weHaveList: allItems}),
            error => console.error(error));
  }

Now it’s time to add data manipulation methods, for this app we will use insert and remove; in both cases we only need to pass the item we wish to insert or remove as the parameter.

Let’s start by updating NewItem

app.js

class NewItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      item  : '',
    };
    this.updateItem = this.updateItem.bind(this);
    this.insertItem = this.insertItem.bind(this);
  }
  render() {
    return (
      <div>
        <p>Add to need list:</p>
        <form
          onSubmit = {this.insertItem}>
          <input
            value = {this.state.item}
            onChange = {this.updateItem} />
        </form>
      </div>
    );
  }

  updateItem(e) {
    this.setState({item: e.target.value});
  }

  insertItem(e) {
    e.preventDefault();
    const newItem = {
      description: this.state.item,
      id: Date.now()
    };

    weNeedList_collection.insert(newItem);
    this.setState({item: ''});
  }
}

Now let’s do the same for WeNeedList.

app.js

class WeNeedList extends React.Component {
  render() {
    return (
      <div>
        <h2>We need...</h2>
        {this.props.items.map(item => (
          <div
            className= 'row'>
            <button
              className= 'remove'
              onClick= {() => this.remove(item)}>
              x
            </button>
            {item.description}
            <button
              className= 'add'
              onClick= {() => this.moveToHave(item)}>
              +
            </button>
          </div>
        ))}
      </div>
    );
  }

  remove(item) {
    weNeedList_collection.remove(item);
  }

  moveToHave(item) {
    weNeedList_collection.remove(item);
    item.user = this.props.user;
    weHaveList_collection.insert(item);
  }
}

And finally for WeHaveList.

app.js

class WeHaveList extends React.Component {
  render() {
    return (
      <div>
        <h2>We have...</h2>
        {this.props.items.map(item => (
          <div
            className= 'row'
            key = {item.id}>
            <button
              className= 'cancel'
              onClick= {() => this.returnToNeed(item)}>
              x
            </button>
            {item.description} from {item.user}
          </div>
        ))}
      </div>
    );
  }

  returnToNeed(item) {
    weHaveList_collection.remove(item);
    weNeedList_collection.insert(item);
  }
}

And we are finished! Now you know all the basics to start building amazing real time apps using ReactJS and Horizon.

The Horizon-React combo greatly simplifies development, allowing you and your team to develop applications and prototypes in a very short time while also making it easy to scale, maintain and debug those apps in the future, this greatly reduces costs and makes you and your team more competitive in the global market.

About the Author:

Building a Realtime Chess Game with React and Firebase

April 6th, 2017

In this quick tutorial, we’re going to build a real chess game that you can play with a friend in real-time.

We’re going to utilize chessboardjs which is a pretty simple library that can render chessboard along with the figures on it. In order to be able to know what moves are allowed and what are not, we will use another library called chess.js. As we will see, those two play very nice together.

For a backend, we’re going to utilize the fantastic Firebase database (a real-time data JSON database now owned by Google). We’ll scaffold the app using the simple React app and will use React Router to handle the routing.

The end result to play with can be found here. The source code is on GitHub.

Let’s get started.

Setting up

Let’s create a new project using create-react-app. This is a handy project from the React team that aims to simplify the process of setting up a React-ready project. It gives us a lot great tools and configuration settings by default. That’s just what we need.

create-react-app chess && cd $_

Now lean back in your chair and wait until it installs all the required packages. To start your newly created application run:

npm run start

OK, now we’re ready to rock.

Adding a router

Our app is going to have two components. The first one, called Home, is going to have just one button for creating a game. The second component called Game is an actual view of the chess game and that we want it to render when the address is “/:token”. Every player will have their own unique token and thus a unique url they can access to play the game.

As you probably guessed, we now need some kind of a router here.

Luckily for us, there is one in React world and a very solid one at that. Behold, the React Router. Let’s install it:

yarn add react-router-dom

Open “src/App.js” and replace its content with the following:


import React, { Component } from 'react';
import { HashRouter, Route } from 'react-router-dom';

import './App.css';
import Home from './Home';
import Game from './Game';

export default class App extends Component {
  render() {
    return (
      
        
); } }

Router listens to url changes and renders the corresponding components. What component to render in each particular case is defined by Route component and its path attribute. If the url is matched to this path, then the component for this route will be rendered.

In our case, it will render Home component when the path is “/”. And if the path is something like “/12345” it will render the Game component.

Note, that we use HashRouter and this is just because it allows the app to be hosted on AWS S3. In general, it doesn’t really matter and you can replace it with more commonly used BrowserRouter.

Intro to Firebase Database

Firebase is a fantastic tool which can loosely be described as backend as a service.

Basically, it lets you store the data, and have multiple clients connected simultaneously and receive the updates in the real-time. So you can synchronize different clients. It can also work offline, has a very thoughtful authentication mechanism and lots of SDKs for every possible platform and a clear documentation.

Sign in to Firebase and create an application. Then you will get a snippet to paste into your html page that looks like this:

  <script src="https://www.gstatic.com/firebasejs/3.7.0/firebase.js"></script>
  <script>
    // Initialize Firebase
    var config = {
      apiKey: "<your api key>",
      authDomain: "<your app name>.firebaseapp.com",
      databaseURL: "https://<your app name>.firebaseio.com",
      storageBucket: "<your app name>.appspot.com",
      messagingSenderId: "<messaging id>"
    };
    firebase.initializeApp(config);
  </script>

That’s it. Now you can read and write to your real-time database. But before we went too far let’s set some restrictions.

Firebase stores your data as a tree. You can assign different access rules and validations to any node of it. By default, any authenticated user can write anywhere. Which doesn’t really sounds like a nice idea, given that our API key will be get exposed as part of our frontend application.

Also, we’re not going to use authentication, so we are going to change the rules a little bit.

Go to Firebase Console > Database > Rules.

Then add this set of rules:

{
  "rules": {
    ".read": false,
    ".write": false,
    "games": {
      ".read": true,
      ".write": true
    }
  }
}

What it’s saying is, disallow any read and write, except for the games node. This is where we are going to store our games.

Creating a new Game

Let’s create our Home component. The only purpose for it will be to create a new game and redirect to the corresponding url.

Our Home component is a function which returns some JSX:


export default function() {
  return (
    

Create a New Game

); }

We use a function here instead of classes because we don’t really need to store any state.

When a user clicks the button we create a new game object:

 const newGame = {
    p1_token: Utils.token(),
    p2_token: Utils.token()
  };

Note that we generate a unique token for two players (in chess, the player who moves first is referred to as “White”).

Then we say to Firebase that we want to create a new node (at this point it will generate a unique hash id for us):

const game = firebase.database().ref("games").push();

And now we save it to database:

    game.set(newGame).then(() => {
    window.location = `/${newGame.p1_token}`;
  }, (err) => { 
    throw err;
  });

The Firebase API is Promise-based. If you’re not familiar with promises it’s never too late to start learning.

If the game is successfully created, we redirect to the game view url by simply overwriting the location url.

Game component

OK, now this is the cornerstone of our game. Here we’re going to build a chessboard (with the help of our friend chessboardjs), we’re going to let user move the figures (but only according to the game rules — chess.js will help with that), and of cause we are going to store the moves into our Firebase database, so that both clients can have their data in sync and be able to play in real-time!

Isn’t it exciting!

Our component is a class because we’re going to need some state to manage. Let’s look at the JSX.

export default class Game extends React.Component {

  // ...

  render() {
    return (
      
{ this.state.turnText }
{ this.state.statusText }

{ history(this.state.moves) }

); } // ... }

The screen is split into two parts here. In the first, there’s a board (<div id="game-board"></div>), in the second there is some additional information, like the links for players, history of the moves, etc.

Let’s initialize our state in the constructor:

  constructor({ match: { params: { token } } }) {
    super();
    this.state = { token };
    this.engine = new Chess();
  }

We get the match variable from the router. It contains our token specified in url and I’m using that fancy ES6 destructuring feature to get it.

Now as you probably know there are two important callbacks in React world: componentWillMount and componentDidMount. We’re going to use the later because we need to do something when after the component is rendered.

 listenForUpdates(this.state.token, (id, game) => {
      this._updateBoard(id, game);
      this._updateInfo(game);
    });

Since we don’t really know what token is that, does it belong to the first user or the second, we have to listen to both games.

function function listenForUpdates(token, cb) {
  const db = firebase.database().ref("/games");
  ["p1_token", "p2_token"].forEach((name) => {
    // getting the ref to node
    const ref = db.orderByChild(name).equalTo(token);
    
    // if the value is changed, fire the callback
    ref.on('value', (ref) => {
      const [id, game] = parse(ref.val());
      if (!id) return;
      cb(id, game);
    });
  });
}

Note that we only calling the callback here when the game exists. Now let’s look at _updateBoard method.

_updateBoard(id, game) {
  const playerNum = figurePlayer(this.state.token, game);
  this.engine.load(game.fen || INITIAL_FEN);

  if (!this.board) {
    this.board = this._initBoard(id, game);
    this.board.position(this.engine.fen());
  } else if (isMyTurn(playerNum, this.engine.turn())) {
    this.board.position(this.engine.fen());
  }
}

First we load so-called fen into our engine which we’re gonna use later to tell us which moves are allowed and which are not.

Next, if we didn’t create the board yet, we create it. Otherwise, we update the existing board by setting position.

And that’s how we create a new board:

  

  _initBoard(id, game) {
    // ...
    const playerNum = figurePlayer(token, game);
    const config = {
      draggable: true,
      pieceTheme: "https://s3-us-west-2.amazonaws.com/chessimg/{piece}.png",
      onDragStart: onDragStart,
      onDrop: onDrop,
      onSnapEnd: onSnapEnd
    };

    const board = ChessBoard('game-board', config);
    if (playerNum === 2) board.orientation('black');
    return board;
    // ...
  }

We provide an id of the element, where we want to place it (game-board) and also several callbacks, the most important of which is onDrop because that’s when the user made his move and we need to update the database:

    

    function onDrop(source, target) {
      // prepare move object
      const m = engine.move({
        from: source,
        to: target,
        promotion: 'q'
      });
      
      // if this move is no allowed, tell the board to revert
      if (m === null) return "snapback";

      // otherwise update game...
      game.fen = engine.fen();
      game.moves = pushMove(game.moves, `${m['from']}-${m['to']}`);

      // ... and save it to database
      games(id).set(game);
    }

Of cause there’s some more to it, feel free to make yourself familiar with the full code here.

Conclusion

So, here it is. We’ve walked through this simple tutorial, created a real-time chess game, and learned to use Firebase Database along the way.

This is of cause doesn’t have to be chess. You can program any kind of game with any number of players. And the nice part is that you can even make it cross-platform. Firebase has lots of SDKs for platforms like Android, iOS, and others.

Firebase is a great way to prototype real-time applications. There’s much more to it in terms of authentication, data validation, working offline, etc. And I hope to cover some of it in coming write-ups.

About the Author:

Using Mobx + Firebase to build a Twitter Clone

March 22nd, 2017

In this tutorial I’ll be showing you how to create a very Twitter Clone using React and Firebase. MobX will be used as the data store for Firebase data. Here’s what the final output is going to look like:

MobX-Firebase Twitter Clone

Firebase Setup

In order to not bog us down in Firebase setup, this tutorial will assume that you already have an existing Firebase project created in the Firebase Console. If not, go ahead and create one. Once you have a project, go to the database section and under the rules tab add the following:

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

This sets read and write permissions of your database to public. This means you don’t need to authenticate later on in order to gain access the database. This is good for quickly getting started with something, but not for production apps. Be sure to change this later!

Project Setup

Clone the create-react-app-mobx project. This allows you to easily create a React Project which has already the MobX toolset built into it (the original create-react-app doesn’t support all MobX features yet).

git clone https://github.com/mobxjs/create-react-app-mobx.git react-firebase-mobx-twitter-clone

Next, open your package.json file and add the following:

"mobx-firebase-store": "^1.0.3",
"react-timeago": "^3.2.0",
"chance": "^1.0.6",
"slugify": "^1.1.0",
"twitter-text": "^1.14.3"

Here’s a breakdown of what each package does:

  • mobx-firebase-store – used for storing Firebase data in MobX maps. This uses Firebase-nest as a peer dependency to subscribe to changes in a Firebase store.
  • react-timeago – used for generating a human-friendly text based on a timestamp.
  • chance – used for generating a random name to be assigned to the current user.
  • slugify – used for making the random name URL-friendly.
  • twitter-text – contains utility functions for working with twitter text. Things like counting the remaining text and converting URL’s into links.

Execute npm install to install all the packages. Once that’s done, you can run npm start to serve the project for development. You can access https://localhost:3000 on your browser to view the project.

Creating the Main Component

Before moving on, delete everything inside the src folder of the project. By default it contains a demo project that uses MobX to implement a counter app. We don’t really need those so you can go ahead and delete them.

Create an index.js file. This is where you supply your Firebase database URL and render the main app component which you’ll be creating later:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

const config = {
    databaseURL: 'https://{YOUR_FIREBASE_PROJECT_NAME}.firebaseio.com',
};

ReactDOM.render(
  ,
  document.getElementById('root')
);

Next, create an App.js file. This is where you import the TweetList component we’ll build that serves as the component that the user will interact with, and the TweetStore store which contains the code for connecting, and saving/reading data from Firebase.

import React, { Component } from 'react';
import TweetList from './TweetList';
import TweetStore from './TweetStore';
import './index.css';

class App extends Component {

  componentWillMount() {
    this.store = new TweetStore(this.props.config); //create a new instance of the store by passingin the Firebase config
  }

  render() {
    return (
      

MobX-Firebase Twitter Clone

); } } export default App;

Creating the TweetList Component

Now we’ll create the TweetList.js file. At the very top, import all the libraries and components that you need. You’ll see how each of these will be used later so we won’t cover what each one does here.

import React, { Component } from 'react';

import { observer } from 'mobx-react';
import { createAutoSubscriber } from 'firebase-nest';

import Chance from 'chance';
import slugify from 'slugify';
import TimeAgo from 'react-timeago'
import twitter_text from 'twitter-text';

const tweet_limit = 140;
var ch = new Chance();

Next, create the Tweetlist component. Initialize the state as well as the functions inside the constructor.

class TweetList extends Component {

  constructor(props) {
    super(props);
    this.state = {
      tweet: '', //the user's tweet text
      username: slugify(ch.name()),
      loading: false, //whether the Firebase data is currently loading or not
      remaining: tweet_limit //number of characters allowed for each tweet
    };
    this.updateText = this.updateText.bind(this); 
    this.submitTweet = this.submitTweet.bind(this); 
  }
  ...
}

The render() method uses the getTweets() method from the store. You’ll be creating this later, for now know that everytime someone makes a change to your Firebase database, the component gets re-rendered. If the Firebase data becomes available, the textarea for entering the tweet and the list of tweets gets rendered.

render() {
  const tweets = this.props.store.getTweets();
  if (!tweets) {
    return 
Loading tweets...
} return (
{this.state.username}
{this.state.remaining}
{tweets.keys().reverse().map(messageKey => this.renderTweet(messageKey, tweets.get(messageKey)))}
); }

Here’s the function for rendering each tweet:

renderTweet(key, tweet) {
  return (
    
@{tweet.username} -
); }

The function for updating the state of the current tweet text and remaining count:

updateText(evt) {
  let tweet = evt.target.value
  let remaining = tweet_limit - twitter_text.getTweetLength(tweet);
  this.setState({
    tweet,
    remaining
  });
}

The function for saving the tweet in Firebase:

submitTweet() {
  this.props.store.createTweet({
    username: this.state.username,
    timestamp: new Date().getTime(),
    text: this.state.tweet 
  });

  this.setState({
    tweet: '',
    remaining: tweet_limit
  });
}

Next, you need to define the getSubs() and subscribeSubs() function. The naming is relevant because the Firebase-nest library rely on these two functions. getSubs() returns the array of subscriptions while subscribeSubs() performs the subscription and returns the function for unsubscribing from the Firebase data.

getSubs(props, state) {
  return props.store.allTweetsSubs();
}

subscribeSubs (subs, props, state) {
  return props.store.subscribeSubs(subs);
}

Finally, you use the createAutoSubscriber() function to subscribe and observe to Firebase data. This function uses the getSubs() and subscribeSubs() functions that you defined earlier in order to subscribe to Firebase data and propagate the changes in the store. It will then return the function that requires a Reactive component to be passed in. We can turn our component into a Reactive one by wrapping it in MobX’s observer() function. This ensures that any data that is used for rendering the component forces a re-rendering when it’s updated. If you don’t set your component as an observer, it won’t re-render when the current user or someone else posts a new tweet.

export default createAutoSubscriber()(observer(TweetList));

Creating the Store

We shall now create out Mobx store. Create a TweetStore.js file. This serves as the store for the TweetList component. It contains the methods for saving and fetching data from Firebase.

Start by importing firebase and mobx-firebase-store. firebase is the official Firebase JavaScript library for working with Firebase. This allows you to connect to Firebase. The mobx-firebase-store library provides a bridge between the Firebase library and the MobX library. It allows you to subscribe to Firebase data through the use of firebase-nest subscriptions. This makes the data flow into MobX’s observable maps.

import Firebase from 'firebase';
import MobxFirebaseStore from 'mobx-firebase-store';

Define the property in which the array of tweets are stored:

const tweets_subkey = 'tweets';

Here’s what it looks like in the Firebase console:

Firebase database subkey

Create the store. Inside the constructor, connect to Firebase and create the store. MobXFirebaseStore accepts a reference to a Firebase database as its argument. Right below that, call super(store.fb) to make the store available inside the class via this.

export default class TweetStore extends MobxFirebaseStore {

  constructor(config) {
    const fbApp = Firebase.initializeApp(config);
    const store = new MobxFirebaseStore(Firebase.database(fbApp).ref());
    super(store.fb);
  }
  ...
}

allTweetsSubs() as you’ve known earlier, returns an array of subscriptions. In this case you only want to subscribe to a single subkey (tweets) and you want its data to be returned as a list (asList: true). Basically, it’s used to specify the subkey in your Firebase database that you want to subscribe to.

  
allTweetsSubs() {
  return [{
      subKey: tweets_subkey,
      asList: true
  }];
}

createTweet() uses Firebase’s push method to push the tweet object into the array. This creates a new item in the tweets array in Firebase which then triggers the subscriber to update the list of tweets for all the connected clients.

createTweet(tweet) {
  this.fb.child(tweets_subkey).push(tweet);
}

getTweets() returns the collection of tweets:

    
getTweets() {
  return this.getData(tweets_subkey);
}

resolveFirebaseQuery() is used for customizing the query used for fetching Firebase data. Here, the results are ordered according to their timestamp and only the 10 most recent tweets are being fetched. That said, Firebase still returns the records in ascending order that’s why you had to call reverse() on the TweetList component earlier to reverse the ordering.

  
resolveFirebaseQuery(sub) { 
  return this.fb.child(tweets_subkey).orderByChild('timestamp').limitToLast(10);
}

Add the Styles

Open the public/index.html file and add the following inside the <head>:


This uses picnic.css to add some default styling to make the project look good.

Next, create a src/index.css file and add the following:

body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

.tweets {
    margin-top: 30px;
}

.tweet {
    padding: 20px;
}

Conclusion

That’s it! In this tutorial you’ve learned how to use MobX to act as a data store for your Firebase data. As you have seen, using Firebase with MobX doesn’t completely change the way you interact with Firebase so you can still use your existing knowledge of the Firebase API. You can check out the code used in this tutorial in this Github repo.

About the Author:

Where Did Vue.js Come From?

March 5th, 2017

Vue.js’s popularity has been climbing pretty fast. It has about 3/4 the number of stars on Github as React, and more than double the stars of Angular. The watchers and forks are also pretty comparable. And the while Vue.js hasn’t nearly caught up yet, you can see a definite trend of relatively rapid growth on Google Trends that is comparable to the growth of React and Angular earlier in their lives.

graph

Angular is still on top, but Vue.js is rising quickly

There needs to be a reason that Vue.js is growing rapidly, especially when the JavaScript framework ecosystem is already filled with plenty of great frameworks. Vue.js doesn’t truly offer anything that other frameworks don’t already have, but it does bring together features from other frameworks in a unique way that may be a better combination. Which of these features did Vue.js glean from other frameworks, and from which ones?

Component-Based

“Component-based” means that the framework is based around creating, composing, and nesting user interface building blocks called components. These components encapsulate everything to do with themselves rather than moving the logic out to a controller or something similar. Components go beyond view objects because they because they can be used directly in the templates as if they were HTML elements:

 

Some Title

Hello

 

React is likely the primary source of inspiration for Vue.js in this area, though you could argue that Polymer and/or Web Components should be considered the inspiration here. I lean toward React primarily because Polymer is designed to actually create custom elements to be used directly in the HTML, whereas React and Vue.js use their components as if they were custom elements only in their templates (JSX in React’s case) and use the rendering engines and template compilers to only give the browser HTML elements that it already knows.

In the end, though, it doesn’t really matter who the idea was stolen from. What matters is that the declarative nature component-based systems are far simpler to use and compose than the imperative, old-school views and sub-views that came with Backbone.js and similar MV* frameworks.

Directives

Directives are a means of control flow and DOM manipulation that are built into the templates and look like HTML attributes. For example:

    • {{ item.message }}

 

 

The v-for attributes is a directive that loops through items so they can all be displayed in li elements. Angular and Aurelia do very similar things. In Angular it would look like this:

    • {{ item.message }}

 

 

And Aurelia looks like this:

    • ${ item.message }

 

 

If you don’t have this kind of control capability embedded in the template syntax, the code becomes more difficult to read because you need to switch back and forth between the template syntax and the JavaScript’s syntax. Once again, the code is becoming more declarative instead of imperative.

Single, HTML-Based Component File

I wrote an article entirely about Vue’s Single File Components and the benefits they provide. It turns out, though, that Vue.js wasn’t the originator of this idea, at least not entirely. Vue.js stole this from Polymer/Web Components. Right on Polymer’s home page, halfway down the page you’ll find an example that looks remarkably similar to a Vue.js Single File Component:

<dom-module id="contact-card">
  <style>...</style>
  <template>
    <content></content>
    <iron-icon icon="star" hidden$="{{!starred}}"></iron-icon>
  </template>
  <script>
    Polymer({
      is: 'contact-card',
      properties: {
        starred: Boolean
      }
    });
  </script>
</dom-module>

Of course, Vue.js goes beyond this by allowing you to use alternative languages for the CSS (Sass, Less, Stylus, CSS Modules), HTML (Pug), and JavaScript (TypeScript, CoffeeScript) due to the required build step. The combination of all of these languages and technologies into a single file may be one of the greatest features for component-based frameworks due to being able to congregate everything related to the component into a single file for better maintenance.

Limited Functionality for Greater Flexibility

Vue.js in and of itself is focused around rendering reactive and interactive user interfaces. It offers little in the way of structure or architecture. This is completely on purpose and it follows pretty much the same pattern as React in this regard. Like React, it lets other libraries handle the extra functionality, such as routing and more advanced, centralized state management. Unlike React, though, Vue.js provides officially supported libraries for some of these things, rather than leaving them up to third parties.

By removing this functionality from the core framework, you get a smaller file size and the flexibility to use other libraries if you want to. The trade-offs are that there are more choices to make and there isn’t necessarily 1 right way to do something because everyone is using something different. By officially supporting vuex and vue-router, though, these trade-offs are mitigated.

Conclusion

Everything is based off of something that already exists, and Vue.js is definitely no exception. Despite having nothing new, though, Vue.js’s growth and popularity most likely came about because it stole and combined many of the best concepts from the other frameworks out there and kept out many of the things that cause headaches for developers.

About the Author:

Build a Camping Weather App with React, Redux and Thunk Middleware

February 7th, 2017

Let’s face it, while it’s fun to write applications from scratch, a lot of software development work involves working with existing code. In this post, we are going to learn how to add a feature to an existing React/Redux app. Following on our previous articles in <list filtering with react/redux> and <component interactivity with react/redux>, we will add a feature to get a weather forecast estimate to help us figure out when is the best time to visit crater lake. In addition, since we are querying an API, we will be learning how to use async actions to retrieve and display the weather.

Here’s an outline of the process we will be following

  1. Adding a date selector component to let the user pick a date for getting the weather.
  2. Getting weather information from the <DarkSky api>
  3. Identifying where and when to update state to incorporate our new weather feature
  4. Handling state changes with async interfaces

Check out the final product on Heroku and get the code on Github.

finished image.png

Adding a date selector

Using the react-datepicker module we’ll create a new WeatherDatePicker component to show the date picker and the forecast results. When the user loads the page they will see “Select a date…”:

date picker.png

After a date is selected, the forecast will be displayed:

date picked.png

Taking a look at the render method in WeatherDatePicker.jsx:

render() {

 return (

 <div>

 Travel Date:

 <DatePicker

 placeholderText="Select a date..."

 selected={this.props.selectedDate}

 dateFormat = "YYYY-MM-DD"

 onChange={(selectedDate) => {

 let newDate = this.checkDate(selectedDate)

 if (newDate) {

 this.props.fetchWeather(this.checkDate(selectedDate), this.props.currentLat, this.props.currentLong)

 }

 } }/>

 Forecast: {this.props.weatherSummary}

 </div>

 );

}

When the DatePicker is opened and a date is selected, firing the onChange event, we first check the date to make sure it is in the future:

checkDate(selectedDate) {

 if (selectedDate.isBefore(this.props.currentDate)) {

 alert("Please pick a date in the future.")

 return undefined

 }

 else {

 return selectedDate.format("YYYY-MM-DD")

 }

}

The DatePicker module uses moment.js for the date object. We can use moment’s isBefore method to compare two moment objects, and display an alert if the user picks a date in the past. If the render method receives a valid result, it calls the delegate fetchWeather, passing along the selected date, to retrieve the weatherSummary.

Now we will add the WeatherDatePicker component and the DarkSky attribution graphic to CampFilterApp.jsx:

render() {

 return (

 <div className="container">

 <div><a href="https://darksky.net/poweredby/"><img src="https://darksky.net/dev/img/attribution/poweredby.png" style={{ width: 100 }}/></a></div>

 <Jumbotron>

 <h1>Crater Lake Camping</h1>

 </Jumbotron>

 <br></br>

 <CampFilterList {...this.props}/>

 <br></br>

 <WeatherDatePicker {...this.props}/>

 <br></br>

 <CampMapContainer {...this.props} />

 </div>

 )
};

While we are working with components, let’s also update the Redux store to include the thunk middleware that we’ll be using for the next steps. We just need to add thunkMiddleware to our createStore call. In index.js:

import thunkMiddleware from 'redux-thunk'

const store = createStore(reducer, applyMiddleware(

 thunkMiddleware

))

Adding state and async actions for the weather feature

Now that we have a component to display the weather, lets look into the associated actions and state needed to do the work.

For the weather feature, the following fields are added to the state in index.js and set as props in CampFilterApp.jsx:

currentDate: today,

weatherSummary: "",

currentLat: 42.9456,

currentLong: -122.2,

selectedDate: undefined

The DarkSky API needs a position and date to retrieve the weather. Since our app is localized to Crater Lake we’ll use those coordinates to retrieve the weather. Don’t forget to convert these new state variables to props to send down to the WeatherDatePicker component in CampFilterApp.jsx:

function mapStateToProps(state) {

 return {

...

 weatherSummary: state.get('weatherSummary'),

 currentDate: state.get('currentDate'),

 currentLat: state.get('currentLat'),

 currentLong: state.get('currentLong'),

 selectedDate: state.get('selectedDate')

 };

}

To query the API and update the selectedDate and weatherSummary variables we will use thunk middleware and fetch as described in this article from the Redux docs.

To handle an async action, we will split the API call into request and receive actions. Our request action, REQ_WEATHER, will update the selectedDate to the value passed from the DatePicker and weatherSummary to “Loading…” to let the user know the weather info is loading. From action_creators.js:

export function reqWeather(weatherDate) {

 return {

 type: 'REQ_WEATHER',

 weatherDate

 }

}

And the corresponding function in reducer.js:

function reqWeather(state, weatherDate) {

 return state.merge(Map({

 'weatherSummary': "Loading...",

 'selectedDate': weatherDate

 }))

}

For the receive action, RECV_WEATHER, we add a response field to our state to hold the JSON returned by the DarkSky API:

export function recvWeather(weatherDate, result) {

return {

type: 'RECV_WEATHER',

weatherDate,

response: result

}

}

The corresponding method in reducer.js for parsing the API response into the weatherSummary field:

function recvWeather(state, weatherDate, result) {

 let content = ""

 try {

 let tempMax = result.daily.data[0].temperatureMax

 let tempMin = result.daily.data[0].temperatureMin

 let summary = result.daily.data[0].summary

 content = summary + " High: " + Math.ceil(tempMax) + " Low: " + Math.ceil(tempMin)

 }

 catch (err) {

 console.log("couldnt get weather summary: " + err)

 }

 return state.merge(Map({

 'weatherSummary': content

 }))

Alright, at this point you may be wondering “This is great and all, but where’s the part where we actually query the API?” Excellent question! That’s next.

Now that we have our request and receive actions setup, lets combine them in the fetchWeather action, which if you recall, is what is getting called from the WeatherDatePicker onChange event:

export function fetchWeather(weatherDate, currentLat, currentLong) {

 let request_url = "https://crossorigin.me/https://api.darksky.net/forecast/8266ff95ef9bbfccf0ea24c325818f31/"

 let weather_str = weatherDate.format("YYYY-MM-DD") + "T00:00:00"

 request_url = request_url + currentLat + "," + currentLong + "," + weather_str

 return function (dispatch) {

 dispatch(reqWeather(weatherDate))

 return fetch(request_url)

 .then(response => response.json())

 .catch(error => {

 console.log("unable to get weather " + error)

 })

 .then(respData => {

 dispatch(recvWeather(weatherDate, respData))

 })

 .catch(error => {

 console.log("unable to parse weather result " + error)

 })

 }

}

Stepping through this piece by piece – first we are constructing the URL for the DarkSky request. As explained in the Redux article, this is where the thunk middleware comes into play; this is what allows the fetchWeather action to return a function instead of an object.

The first thing the returned function from fetchWeather does is dispatch the reqWeather action to update the UI showing that we are requesting the weather. It then fetches the response from the DarkSky API, dispatching the recvWeather action if it receives a valid result.

Now, we have all the plumbing hooked up to retrieve the weather based on the date chosen in the date picker. Give it a try and download the code. If you want to make updates and deploy your own Heroku app make sure to link the create-react-app buildpack in Settings.

Some next steps to try:

  • Allow the user to get customized forecasts for each campground by modifying the CampListItem component to fetch the weather, as opposed to retrieving a general area forecast as we did in this post.
  • When querying the DarkSky API instead of just getting a daily forecast, look for a week before and a week after and get an average, high, and low temp to give a better idea of seasonal weather patterns