Last night I released a new library to GitHub and npm called React PouchDB components. I'm excited to share this library, which started as an experiment to illustrate to my friend Jon how easy it could be to leverage PouchDB in React. After enough tooling around I suspected that the pieces could be extracted and shared more broadly.
Blog Posts
A working example of what I'm going to describe here can be found at https://github.com/stanlemon/example-relay-app.
For awhile GraphQL has looked interesting to me, like something I wanted to learn. I love the concept of strongly typing expressive queries that can be batched into a single request. That's GraphQL, a technology that really seems to shine in UI work for single page apps (SPAs).
Relay is Facebook's GraphQL framework for React, it's really where GraphQL got its traction from. I love React and spend a good portion of my hobby time building stuff with it, so GraphQL was a natural progression for me. The problem is that documentation and examples on how to use Relay are all over the place and it's even harder to get into if don't already have a working GraphQL server. Some might point out that Apollo is a much easier place to start with React & GraphQL and that definitely seems true, but I specifically wanted to familiarize myself with Relay.
My first challenge was a working GraphQL server that I could issue queries against. Fortunately PostGraphile] makes this super easy. You need a Postgres instance to get going, but after that you have a working GraphQL server over top of a Postgres database. I won't go into how to setup PostGraphile, it's documentation is actually rather than good and there are some additional environment notes in the repository with my example code.
Querying from within Relay is pretty easy and straightforward and the documentation that Facebook offers is adequate. If you want to play around with querying check out this GraphQL playground with Star Wars data, it's pretty fantastic! GraphQL is not just for fetching data though, it also allows you to create, update and delete it. Those operations are called mutations and their documentation is a lot less clear.
A mutation in and of itself is not complicated, there are really two parts to it: (1) the mutation definition and then (2) committing the mutation to the GraphQL server. That looks like this:
import { graphql, commitMutation } from 'react-relay'
const mutation = graphql`
mutation AppCreatePersonMutation($input: CreatePersonInput!) {
createPerson(input: $input) {
person {
id
firstName
lastName
}
}
}
`
commitMutation(environment, {
mutation,
variables: {
input: {
person: {
firstName: "Stan",
lastName: "Lemon"
}
}
}
})
In the app I built I had already loaded all of the person records from my database using a query like this:
query AppQuery {
allPeople {
nodes {
id
firstName
lastName
}
}
}
When I first got this working I naively expected the properties in the react component that came from this query to update, such that my new person would appear in my list. But alas it did not! Updating the state store for relay is not straight forward. The mutation documentation on relay's site has some clues, but I ended up struggling to implement what I thought was a pretty straight forward user case: updating the list of nodes from my initial query with a new record.
Make sure your createPerson() mutation is returning the same fields as your allPeople query, and also make sure that allPeople is returning id. Matching fields in the response is important for new records. If you're only doing updates you can get away with returning just the fields you've changed, but the example below does not cover partial updates. The id field is not actually required for create mutations like this, but as soon as you start working with updates you'll thank me as the the global graphql id is the easiest way to yank an existing record out of the store.
What we need to do now is define an updater function on that the second parameter to commitMutation(). This updater receives a single parameter, the store and this is where we will do our handy work.
Inside the updater function the first thing we want to do is get the portion of the store where allPeople is at, because this is what we need to modify. We need to put our new person into the list of person records in that part of the store, which will in turn trigger the update to our UI. This is actually pretty easy to do as long as you know the key to pass the get() method. I found this out using the replay-devtools, which I highly recommend installing.
const allPeople = store.get('client:root');
Now we have the container of the query. Because we're using PostGraphile everything is nested under nodes so we actually need to yank that out from under our allPeople variable. That looks like this:
const nodes = allPeople.getLinkedRecord('allPeople').getLinkedRecords('nodes');
We also need to get the person record that our GraphQL server returned to us and then yank the payload from it. The payload in this case is that new person we created.
const payload = store.getRootField('createPerson');
const newPerson = payload.getLinkedRecord('person');
We have the original list of persons and the new person we added, now we need to combine them, this is really easy using the spread operation:
const newNodes = [...nodes, newPerson];
Now we have the full list of person objects as they exist in our database. Keep in mind if you were sorting these somehow with graphql you will need to insert the newPerson into the proper place, not just blindly at the end like we are doing. Lastly we take that new nodes list and replace it in our allPeople portion of the store like so:
allPeople.getLinkedRecord('allPeople').setLinkedRecords(newNodes, 'nodes');
Once this is done the local store in your react component will re-render with the new data.
Keep in mind, this is a root level scenario for the component in question. It seems pretty simple, but good luck finding an example that works like this one. If you're using data nested under another object (like comments on a post) than there are plenty of examples on the web more suited to that scenario, examples that involve things like the ConnectionHandler.
You can find all the code for my working example over at https://github.com/stanlemon/example-relay-app
I do my best to avoid social media, and even when I do participate I consume a pretty narrow set of content. For example, my twitter is highly curated to focus on Indianapolis municipal happenings, Apple product rumors and javascript news. On the rare occasion I login to Facebook it’s mostly to respond to messages on my podcast page or to look at old pictures of Chicago North Western trains. I rely on my lovely wife and podcast cohort Jon to keep me in the know on the latest and greatest internet fads, at least the ones that stir up enough trouble to warrant a text. It really is a top notch curation system.
This week the Gillette “The Best Men Can Be” commercial somehow bubbled its way up into my view and I read reactions from both the political left and the political right on how wonderful and how terrible this commercial is. If you’re not familiar with the video you can find it on YouTube. Like so many things today it yielded truly polar reactions. Those that loved it applauded it for calling out what some refer to as “bro culture”. Those that hated it claimed it vilified all men universally.
Here’s what annoys me about this whole thing: Gillette won and everyone else lost. Anyone who thinks Gillette was somehow in pursuit of altruism forgets the age old axion that “any press is good press”. Gillette is owned by Proctor & Gamble, a behemoth of consumer goods based out of Cincinnati. It is a publicly owned and traded company whose sole purpose is to generate profits for its shareholders. Let that set in a minute. Gillette exists to make money, plain and simple.
In 2015 Gillette was the #1 shaving company in the United States, holding onto 64% of the market with runner up Schick. By all accounts both Gillette and Schick make crappy shave products. Both companies sell dull cartridge blade systems that generate an absurd amount of waste, but I digress. In recent years, Dollar Shave Club encroached onto Gillette’s market share by more than a razor’s edge, resulting in a 1 Billion dollar purchase by Unilever. Even beyond sub par subscription services like Dollar Shave Club, you have stores like The Art of Shaving popping up everywhere and a general interest in the more classical safety razor genre of equipment. All this is to say, Gillette is hurting. Its relevance is shriveling up and it needs some life kicked back into its blood. Don’t believe me though, take a look at Procter & Gamble’s stock prices. In a hugely volatile year on the stock market $PG is basically untouched. That’s not what share holders want to see, they want growth!
Gillette has to be loving all the PR it’s getting. Again, any press is good press. People who weren’t talking about Gillette are now, and a product that was not memorable is now gliding its way onto everyone’s social media feeds. So if you loved the video, maybe you’ll go out and buy some Gillette razors in support of the company and its bold position in this video. That’ll help Procter & Gamble’s quarterly sales, and that’s exactly what they want. Or maybe you hated the video, feeling like it unilaterally vilified half the population with stereotypes. If Gillette is lucky, you took to social media to complain about it, or shared some article or other post and further perpetuated their ad campaign. The best advertising is free, and you played right into Gillette’s hand. Either way, Gillette is on everyone’s mind, and that imprint will linger for a bit.
It really doesn’t matter where you stand on the issue, because in the end Gillette won. Nothing has changed, we’re just as angry and polarized as we were before the campaign, if not more so.
Gillette is in good company though. We hate to admit it, but this sort of appeal to our heart strings style advertising - which has absolutely nothing to do with the product being sold - is increasingly common. Tune in on a Sunday and the NFL is talking up fighting cancer and other diseases as well as supporting the military. Don’t be confused that these are somehow honest appeals. At the end of the day it’s just another ploy to get you to tune in and watch the real product, a football game. If you support our military and it appears like the NFL does, you tune in to support them, thus increasing their viewership and further increasing the cost of advertisement on one of the sacred NFL commercial slots. That’s the end goal of these heart string campaigns.
Don’t get me wrong, there are honest folks who mean well by participating in these campaigns their companies put on. I really don’t mean to discount the intent of both NFL players and Gillette employees, I just think we need to be honest about what drives campaigns like this. As much as I would love for it to be, it’s not altruism. We shouldn’t somehow project that onto the marketing departments of these big economic machines who ultimately have dividends to pay every quarter.
On an unrelated note, if you are either thinking of buying Gillette products because you loved the video or if you are thinking of no longer buying Gillette products because you hated the video let me take this opportunity to appeal to you. There’s a better way! Get yourself a good ol’ Merkur safety razor and some Astra blades and enjoy a better shave. Chances are you’ll support a smaller business in the process too, winning all around.

In Episode 8 of Life with a Twist of Lemon my friend Jon asked me about buying a house and for part of that discussion we talked about mortgages. One of the things that I mentioned our family does is visualize our mortgage on a piece of paper hanging on the side of our refrigerator. On the paper is a drawing of a house, which my lovely wife made to look like our actual house. It’s on graph paper and each square represents part of the mortgage we owe. As we pay down the mortgage we fill in boxes, with the ultimate goal of having the whole house filled in. This idea didn’t originate with me; I don’t actually even recall where I first saw this. I think it’s neat though, and I like that it’s there every day for us to see. A few listeners (it still amazes me that we have those, thank you mom and the other 3 folks that tuned in) asked me what that mortgage visualization looks like, so I thought I would share it here. The colors don’t mean anything, they were chosen based on the closest colored pencil at the time. The shaded parts (roof and windows) also don’t count in our drawing. Anyone can do this too, and you don’t need to be as fancy with the drawing as Mrs. Lemon was. That said, I think ours is pretty cool and I’m just tickled with what she made for our family. Now to fill it up!
The purpose of the drawing and really a good portion of Jon’s and my discussion is understanding your debt and having a strategy to get rid of it. I don’t think debt is in and of itself a bad thing. In many instances it’s simply a necessity, like buying a house. I do think society is perhaps too comfortable with debt though and it’s good to go into something like a mortgage with a desire not to have it. That desire is strong in me, and things like this visualization help keep it top of mind so that I am constantly being reminded to get rid of it.

For more than a couple of years now my friend Jon Kohlmeier has been trying to persuade me to start a podcast with him. We’ve routinely joked about it, but I’ve resisted getting it started because of time and other trivial things. Jon and I have been friends for well over a decade now and our roots to podcasting go way back. Jon was the cohost and producer of the Higher Things Radio podcast with another friend of mine, Rev. George Borghardt. I appeared a number of times on that podcast, and there are more than a couple of episodes where it is just Borghardt and I just shooting the breeze. I think that’s where the idea for Jon’s and my podcast came from, because really Life with a Twist of Lemon is just the two of us shooting the breeze. Jon likes to say we’re just recording the conversations we were going to have anyway, and if it wasn’t for the fact that we schedule the recording that’d probably be spot on.
So this is my latest project, a podcast where I just talk with my friend Jon. There’s nothing prescriptive about what we’re going to discuss fro one episode to the next. We’re going to try to keep it to thirty minutes or so, because we don’t particularly care for long podcasts ourselves. We plan to keep it fully rated G because I’ve got kids and I want them to be able to be safely in ear shot. Right now I’m having a lot of fun doing the podcast; more fun than I thought I would. If I’m lucky, we’ll get a listener other than my mom and dad, and if not then my kids can look back on this project in a few years and laugh about it.
Oh and about the name... as vain as I am, would you believe it wasn’t my idea? No, really! Jon came up with the name and, because I have no modesty in my blood, I happily obliged to using it.
You can find our podcast on iTunes and most likely whatever podcast app you’re using. I use Overcast, a fantastic and free podcast for iOS, and recommend trying it out if you’re not already using a podcast app. The topic is constantly changing so pick an episode that interests you and give it a try, worst case scenario we’ve wasted thirty minutes of your time!
And apparently we've got a Facebook and Twitter page too, if you're into that sort of thing. (Thanks Jon!)
