Unconventional Conventions with React

November 11, 2017

Me and React

React is an awesome declarative DOM library with a lot of dynamic elements and aside from JSX, (and not even that) not much in the way of telling you what to do and how to do it. I’ve started looking into React in early 2015 and I was instantly confused. At the time the HTML in JS approach that JSX brings to the table seemed foreign to me, but since then I’ve learnt to use it and love it for all the power it brings to you as a developer, when you need to deliver a very stable and easy-to-scale web application.

What’s convention?

The thing is with React as opposed to fully-fledged frameworks, like Angular, is that your usual workflow is not simply installing the starter kit and then smashing away at your keyboard, following a strict guide-line and what’s essentially a different API - almost making it trivial for you - the developer - to learn a new language, a set of practices needed to complete the task.

When it comes to libraries, like React, you’re not forced to taking a certain approach, which ultimately also adds an extra step in your development process: deciding what conventions to follow. This step is essential though, because having no pre-defined rules or guidelines to follow initially really sucks. It will lead you down a road of having a hard to understand, hard to debug, very diverse (in the wrong way) code base.

Why is that an issue?

I really isn’t, if you’re the only one developing your application and once you’re finished you ship it off and never touch it again. Believe me, I may have done something like that once or twice in my dark past. Trouble comes when you end up having to touch that ghastly code or heaven forbid have another developer having to work with it. You will not be thanked, that’s for sure.

How to solve that issue?

From what I’ve seen in my journey of working with most things from jQuery and AngularJS all the way to React, Angular2+ and Vue is that even though of these, React is the one that warrants the least amount of conventions baked into using it out of the box, it is actually the one where you’ll instinctively start using your brain and your brain will promote coding habits that are generally great for performance and easy to reason about. It’s called convention. You can further that by following a stricter set of rules, enforced by a linter. One example of such rule sets is AirBnB’s ESLint rules.

What’s unconventional

Up until then it’s not been clear what this post is all about. So I’ll tell you now. I wanted to highlight some of the not-so-used features or possibilities of React and maybe shed some light on why they’re not used so much or what are the better alternatives. Let’s dive in.

Using components to transform strings expressively

Since React 16, you can return a string from a React Component. I believe this feature has not seen use to its full potential. Other frameworks, like Angular give us a way to work on strings and other data to be displayed via pipes. Since in Angular you put your display logic in an HTML file, implementing a simple pipe would look like this:

import { Pipe, PipeTransform } from '@angular/core'

@Pipe({ name: 'capitalise' })
export class CapitalisePipe implements PipeTransform {
    transform(value: string) {
        return value[0].toUpperCase() + value.slice(1)
    }
}

That’s TypeScript and an Angular Pipe contructor. As you can see there is a lot of convention going on there. Here’s how you use it:

<p>{{ 'hello, world!' | capitalise }}</p>

What about React?

In React you don’t have a de-facto way of doing this, instead what you have is JavaScript and its built-in features and luckily it can be done with a simple function, like so:

function capitalise(value) {
    return value[0].toUpperCase() + value.slice(1)
}

… and later on …

<p>{capitalise('hello, world!')}</p>

which will give us the same result and we’re already seeing that it’s not too far from plain ol’ JavaScript, when you take out the JSX part. Let’s unconventionise (that’s a word from now on) this with the new React 16 feature.

function Capitalise({children}) {
    return children[0].toUpperCase() + children.slice(1)
}

Which would give us a chance to do this in our JSX:

<p><Capitalise>hello, world!</Capitalise></p>

Obviously for this (and most other) use case it’s kind of redundant and large, which is why I belive it may not gain a lot of traction in the community. What I believe it could be an interesting use case, however is for internationalisation. In React there is really no best way to do internationalisation, but there are several ways. Let’s explore my way:

At the top level we need a translation provider, which will load the keys and values for translations in JSON format, much like you would in Angular (sorry, I use Angular at work as of lately). Later down the line when you need a translation, you can call for it via its key. I’ll make it simple - it will not support nesting for now.

class LanguageProvider extends React.Component {
    static childContextTypes = {
        translations: PropTypes.object,
        translationsLoading: PropTypes.bool,
        currentLanguage: PropTypes.string
    }

    state = {
        translations: {},
        isLoading: false
    }

    async componentDidMount() {
        this.setState(() => ({isLoading: true}))
        await this.loadTranslations()
    }

    async loadTranslations() {
        // ... load translations
        this.setState(() => ({translations, isLoading: false}))
    }

    render() {
        return this.props.children
    }
}

We also want to provide an easy way to incoorporate these translations in our app, so let’s have us a component that pulls in from context and uses the key to retrieve the proper value.

const T = (
    {
        children
    },
    {
        translations,
        translationsLoading,
        currentLanguage
    }
) => translationsLoading ?
    null :
    translations[currentLanguage][children]

T.contextTypes = {
    translations: PropTypes.object,
    translationsLoading: PropTypes.bool,
    currentLanguage: PropTypes.string
}

As you can see that’s pretty simple. We use the context and unless it’s loading we return whatever the string value is. Using this would be very simple, let’s see how:

<h1><T>homeTitle</T></h1>

In our language file we’d have something like:

{
    "homeTitle": "Welcome to our site!"
}

Conclusion

As you saw there, there are some non-conventional methods of writing React applications that may yield positive results. Stay tuned to find out more about the subject.