How to share React components across platforms

We will be looking into how you can share some of your visual React components between the web platform and the native platforms by utilizing CSS-in-JS libraries and their primitive functionality.

That will all make sense when you are done reading the article, but first some introduction is in order.

In programming there is a principle called DRY (Don't Repeat Yourself). When it came to cross platform products eg. products that need an iOS, Android and a web application most products unwillingly subscribed to DRY's frustrating sibling WET (We Enjoy Typing, Write Everything Twice, Waste Everyone's Time).

Mostly this was due to a language barrier. iOS was Objective C or Swift, Android was Java or more recently Kotlin and web was JavaScript or the multitude of alternatives that transpiles to JavaScript such as Typescript, Elm etc.

React Native was not the first to break the language barrier, but was definitely the biggest on the scene to unite all three platforms under one language, JavaScript and as a side effect the React framework.

That is all well and good. Now we can share state management, business logic and general application architecture between all three, but what about the actual sharing of components? What about styling?

On the web the most basic React link is styled with inline styling.

import React from 'react'

const style = {
  color: '#fff',
  fontWeight: 600
}

const Link = props => <span style={ style } { ...props } />

Usage example follows below.

const App = () => {
  return (
    <div>
      <h1>Reload</h1>
      <a href='https://reload.dk'>
        <Link>Home</Link>
      </a>
    </div>
  )
}

render(<App />, document.getElementById('root'))

Simple, but it is missing a lot of the niceties we get from CSS such as media queries and pseudo-classes. So a lot of React codebases you will see has the styling separated in its own stylesheet in a more classic fashion.

.link {
  color: royalblue;
  font-weight: 600;
}

 

import React from 'react'
import './Link.css'

const Link = props => <span className='link' { ...props } />

With the help of CSS modules you also have the ability to locally scope your classes to this one component. But that's another story.

A more recent trend has been the CSS-in-JS movement.

This paradigm allows you to write your styling in JavaScript which then transpiles down to stylesheets.

This means you get capabilities of a full programming language plus the performance of the CSS engine build into the browsers.

There are a couple of different libraries that allow you to write CSS-in-JS, but I'll show you styled-components and glamorous.

Emotion is also worth mentioning, if you were to do web only. At the time of writing they have no native or primitive implementation and no desire of making one.

The choice between styled-components and glamorous for your project is not an obvious one.

The syntax is different, the functionality is more or less the same.

The beauty of both of them and where the added abstraction of CSS-in-JS starts to shine is when we get to cross platform styling and some would say a more semantic component (tag) usage.
glamorous and styled-components have primitives which allow the developer to make components that look and feel more or less the same across all three platforms.

import glamorous from 'glamorous-primitives'

const Link = glamorous.text({
  color: 'royalblue',
  fontWeight: 600
})

export default Link

As you can see in the code examples above and below, the main difference is the usage of an object literal in glamorous and a template literal in styled-components.

Another difference is the camel cased nature of glamorous and the kebab cased or should we say CSS nature of styled-components.

import styled from 'styled-components/primitives'

const Link = styled.Text`
  color: royalblue;
  font-weight: 600;
`

export default Link

More importantly, this allows a team of developers to create a library of primitive React components that can be used and extended across platforms.

We can get closer to an even more DRY code base and the product has an easier time retaining its visual identity across platforms.

Whatever CSS-in-JS library you end up choosing or not choosing the movement towards easier to maintain cross platform products is a great one to be a part of.

This is just an appetizer, but there is so much more to modern React component creation and CSS-in-JS.
We made a small playground on StackBlitz if you would want to try some of this yourself.

(Psst even React VR applications can make use of the cross platform component).

If you are into TypeScript we made a small example of how glamorous and styled-components fits into that space as well.

Here are some useful resources if anyone wants to jump down the rabbit hole of cross platform React components together with Reload.