Headshot of James Moss

James Moss

I’m a freelance full-stack engineer with over 15 years experience. Currently taking on new React based opportunities, drop me a line 👋

Using React hooks in class components

Unless you’ve been living under a rock for the last 6 months you’ll know that hooks in React are the new hotness. There’s now a hook covering almost every single browser API plus many more. Adoption in the community has been widespread to say the least.

Hooks aren’t perfect right now, their API doesnt fully replace class methods yet and developers are still learning how to use them effectively; it’s a brand new paradigm to learn. In large codebases lots of legacy components still use classes, but you might want to use some awesome behaviour you’ve added in a new hook without having to rewrite code.

What if we could use these hooks we’ve written in class based components?

One option is to import another library that (probably) doesn’t use hooks and use their existing API. This is bad for several reasons

  • More dependencies means more code and therefore higher surface area for bugs
  • Multiple dependancies doing the same or similar things
  • Additional chores when upgrading
  • Higher bundle size

There is however a way you can write new behaviour as hooks and still use them in class components.

Hooks first

Imagine a straightforward hook that uses the window.online/window.offline events to monitor if the user’s device is online. If the user goes offline we might want to re-render and show an error message instead. When the user reconnects to the network we want our app to render the UI again. In reality you’d probably want to make your app more progressive but this simple example will do for our purposes:

import useNetworkMonitor from 'useNetworkMonitor';

const App = () => {
	const isOnline = useNetworkMonitor();

	return isOnline ? <Index /> : <OfflineError />;
};

One of the benefits of hooks is that they reduce cruft in your component tree. Over the last few years as the render props pattern has taken off we’ve started seeing more components being rendered that don’t have any influence on the UI, they’re just passing state and props down to another component. These components are important as they allow inversion of control; your child component can access state from within the parent component without them having to know about each other. However, as they start piling up in your components, you’ll find that the component tree becomes polluted and therefore debugging becomes harder.

Although hooks aims to reduce these kinds of components, we can actually leverage them to add support for classes via render props with minimal extra code:

const NetworkMonitor = ({ children }) => {
	const isOnline = useNetworkMonitor();

	return children({ isOnline });
};

<NetworkMonitor>
	{ ({ isOnline }) => (
		isOnline ? <Index /> : <OfflineError />
	) }
</NetworkMonitor>

What if you’re already using the render props pattern to add behaviour like this in an existing code base using a class based component? Good news, you can convert your render props component to a hook, implement the above pattern and slowly over time phase out usage of the class component.

The points discussed in this article are probably not a massive revelation to most readers but they are important. Right now the React API is undergoing a transition as Suspense and async rendering comes along; established patterns and best practises are changing rapidly. I’d really love to see hook authors start implementing this bridge component pattern, allowing both modern and older React code to play together nicely as well having as a clear migration route towards a hooks based future.

Going even further with higher order components

Remember HOCs? You might still be using them. Well we can apply the same pattern here as well:

function withNetworkStatus(ComposedComponent) {
	return function NetworkMonitorWrapper(props) {
		const isOnline = useNetworkMonitor();

		return <ComposedComponent { ...props } isOnline={ isOnline } />;
	};
}

// <Index /> component now has an isOnline prop injected
withNetworkStatus(Index);

This is probably one step too far. Don’t do this.

Summary

So just to recap:

  • Write your hooks as you have been doing already
  • Add a render props / function-as-child bridge component for use in class components
  • Add a HOC if you’re a little bit crazy

Embark - A hyper minimalistic new tab page for Chrome

The new tab page in your browser is something you look at hundreds of times each week but you probably don’t put much thought into what appears there; most of the time it acts an interstitial page that flashes up briefly before you stick a URL or search term in the address bar and navigate away.

There’s quite a few new tab page extensions that replace the default out there already for Chrome. I’ve tried most of the popular ones but they all suffer from similar problems:

  • Feature overload Do you really need to check your stocks, weather, todo list and news feeds from your new tab page? Don’t even get me started on the saccharine motivational quotes.
  • Speed Your new tab page should be fast to load and not get in the way of you using your browser. Due to the previous point this is usually not the case.
  • Bad imagery I don’t want to see cheesy, overprocessed (and sometimes 3D rendered) images every time I hit that new tab button.

Frustrated with the bloat, lack of customisation, poor photography and slow loading speeds of similar new tab extensions I’ve built my own.

Screenshot of Embark

Embark replaces Chrome’s default new tab page with a pared back design and beautiful photography. It’s a gentle reminder throughout the day of the current time and some nice eye candy before you set off into the Internet.

I’ve just released version 0.4 and you can grab it right now from the Chrome Web Store.

Screenshot of Embark

There’s deliberately just a small selection of features at the moment but each one is highly customisable through the options page. I’ve really focused on ensuring Embark loads blazingly fast and uses as little system resources as possible.

If you install it and like it please leave a good review on the Chrome Store.

Support for Markdown in OSX QuickLook

QuickLook is an indispensable feature in OSX that I use many times every day. Highlight a file in Finder and tap space to see a preview of the file without having to open it in an editor.

Recently I’ve been writing more and more documents in Markdown using Mou (including this blog post). Frustratingly, out of the box QuickLook doesn’t support Markdown, you’ll just see a larger version of the file icon.

There’s an easy fix however in form of Phil Toland’s QLMarkdown. Installing it is easy:

  1. Download the latest release by clicking here.
  2. Extract it somewhere temporarily and copy the QLMarkdown.qlgenerator file into ~/Library/QuickLook (you may need to create this directory).
  3. Relaunch Finder by alt+right-clicking on the icon in the dock and selecting the option at the bottom.

Boom. Markdown in QuickLook.

Save time with SSH aliases

If you’re a developer you probably find yourself connecting to servers over ssh several times each day. Remembering the server address, port, user and password can be hard - but it doesn’t have to be.

You might find yourself needing to use the following to get into a server:

$ ssh -p 3241 james@somehost-532242.long.example.org

Then you have to remember (or maybe even lookup) the password. It’s pretty tedious and time consuming. You could create a bash alias for each server but it’s not ideal; there’s a better way.

~/.ssh/config

Within this file you can define the hostname, user and port of a server and associate it to a short name like mainserver.

The syntax us fairly straightforward, here’s an alias based on the previous example.

host mainserver
  hostname somehost-532242.long.example.org
  user james
  port 3241

Now if you want to connect, you just need to type:

$ ssh mainserver

Much easier to remember. As an added bonus, scp also observes the alias so transferring files is now pretty simple.

# transfers access.log from the server to the current directory
$ scp mainserver:/var/log/access.log .

ssh-alias

I’ve put together a set of ruby scripts which makes it easy to add, delete and list the aliases in ~/.ssh/config.

Installation is simple:

1
2
3
$ git clone git://github.com/jamesmoss/ssh-alias.git
$ cd ssh-alias
$ chmod +x ./*

You’ll also obviously need ruby installed. It comes with OS X by default.

To add a host run ./ssh-alias-new.rb and follow the prompts. The script also takes care of transferring your public key to the server so you won’t have to re-enter your password every time you connect.

If you want to remove an alias use ./ssh-alias-delete.rb and follow the prompts. ./ssh-alias-list.rb will print a list of every alias you’ve got setup.

The code is up on github if you want to fork or send a pull request. This is my first proper ruby project, so go easy on me.

Blog redesign

What you’re looking at here is the new version of my blog.

I’ve decided to pare back the design to make the content really stand out, focusing on clean typography (from TypeKit), vertical rhythm and minimalism. There’s one full post per page (no read more links) and comments are only visible on the permalink pages.

Under the hood

The changes aren’t purely cosmetic. I’ve been using WordPress for the last few years, and it’s served me well, but I’ve become increasingly unhappy with how complex it makes writing blog posts. The process and distractions of logging in, messing around with the HTML in a WYSIWYG editor (it always needs manual fixing) and publishing it puts up a barrier which stops me from blogging as much as I’d like to.

Jekyll

To that end I’ve been looking for something a lot simpler. I started looking into writing something lightweight with Silex but didn’t have the time to build and test anything substantial.

In the end I came across Jekyll, written in Ruby, which is a “blog-aware, static site generator”. You feed it some content and a HTML layout and it combines the two, generating the final flat pages to be served to your visitors.

Content can be written in Markdown, Textile or plain ole’ HTML. A snippet of YAML Front Matter at the top of each post can set metadata such as categories or tags. I’ve decided to use Markdown, it generates clean semantic HTML with the least amount of effort. A range of importers makes migrating content from another blogging platform super easy.

I don’t get to use Ruby as much as I’d like to so I’m hoping Jekyll will give me a chance to do some hacking, I’ve already thought of a few ideas for plugins.

Code highlighting

I want to start using this blog to post more code snippets and review other open source projects. I’ve enabled Pygments within Jekyll which automatically highlights my code snippets. I’m using the monokai theme (as I do in my usual code editor) which contrasts well against the rest of the page:

class Employee < Person
  def initialize(fname, lname, position)
    super(fname,lname)
    @position = position
  end
  def to_s
     super + ", #@position"
  end
  attr_writer :position
  def etype
     if @position == "CEO" || @position == "CFO"
         "executive"
     else
         "staff"
     end
  end

Pygments is brilliant. It’s got support for all the popular languages (and some less popular ones). I particularly like how I can display shell commands:

$ chmod 664 myfile
$ ls -l myfile
$ grep -v apple fruitlist.txt

Finally I’ve added some inline code styles to make distinguishing them from the rest of the body text easier.

Hosting

The beauty of having flat HTML files is that you can host your site literally anywhere, there’s no need to install and configure complex web servers (I’m looking at you Apache). Because of this I’ve decided to host the site with GitHub.

GitHub Pages allows you to publish content to the web by simply pushing content to one of your hosted repos. It’s also got support for Jeykll baked in (no surprise, the author of Jeykll is also a GitHub co-founder). It’s free, which should cut my hosting costs every month, and leverages GitHub’s scalability and reliability.

The Future

I particularly like the open-source nature of my new blog, you can see all my source code and commit history on GitHub. This is just the start of more planned changes too, I’ve got a lot more work to do over the next few months to get the site to the point where I’m happy. I’m hoping this change to simpler blogging software will spur me to publish better content, a lot more often.