Advanced React Native styling with a few lines of code

I came to React Native world recently. However, I do have a lot of experience with Reactjs environment. I used to use Glamorous lib (nowadays evolved into Emotion.sh) for maintaining of CSS styles in my Reactjs apps. And that was exactly what I have been missing in React Native space.

I did not want to use anything complex because my React Native app should be simple. However, I still wanted some kind of abstraction because otherwise the project code boilerplate can get messy quite easily. Mainly, I wanted to be able to use React Native elements, easily modify its styles, create a reusable components, and overwrite its styles in its descendants.

Requirements

  1. Simple and familiar interface.
  2. Works with React Native elements (and any other React component).
  3. Component styles composition.
  4. No need use of React Native StyleSheet (enhanced style property).

Here is an example:

  1. I want to use built-in Text component.
  2. Inherit its styles, add custom ones and create a component which will be available across my app.
  3. Inherit this custom component, modify its styles (or add new ones) and render it on my screen.

It can be done quite easily with a simple component abstraction/composition:

  import { Text } from 'react-native'

const Headline = styled(Text)(() => {
return {
fontSize: 20,
textAlign: 'center',
margin: 10
}
})

const BoldHeadline = styled(Headline)(() => {
return {
fontWeight: 'bold'
}
})
<BoldHeadline {...{style: {backgroundColor: 'red'}}}>My Headline</BoldHeadline>

Our abstraction which allows us to do this, is wrapped in styled method which can looks like this:

import React from 'react'
import { StyleSheet } from 'react-native'

const styled = Component => {
const comp = styles => {
return ({ style, children, ...rest }) => {
let composed = []
if (styles) {
composed = [
...composed,
StyleSheet.create({
styles
}).styles
]
}

if (Array.isArray(style)) {
composed = [...composed, ...style]
} else if (style) {
composed = [
...composed,
StyleSheet.create({
style
}).style
]
}

return <Component {...{ style: composed }} {...rest}>{children}</Component>
}
}

return arg => {
if (typeof arg === 'function') {
return comp(arg())
}

return comp()(arg)
}
}

export default styled

Styled function allows us to use its components in two different ways:

  1. As a component wrapper (for the composition).

It allows us to take any component, overwrite its styles and return a new component. As is shown in the example above:

const Headline = styled(Text)(() => {
return {} // your styles goes here
})
const InheritedHeadline = styled(Headline)(() => {
return {} // another styles here
})

2. As a component “enhancer”.

If you don’t want to define any styles at component declaration level but you want to be able to use style property later on:

const CustomButton = styled(Button)<CustomButton {...{style: {backgroundColor: 'black'}}}>Label</CustomButton>

Styled function is very simple as you can see, but it allows us to do quite a lot of stuff for better components maintenance, reducing code complexity and better code readability.

I took the code above and created npm package called styled-react-native.

You can start using it as well by adding package into your dependencies with command:

npm install --save styled-react-native

and in your project:

import styled from "styled-react-native"
const CustomText = styled(Text)

Thanks for reading! I hope you found this helpful. 🤩


By the way, I’m now on Twitter too if you’d like to follow more of my code hacks.

HackerNoon.com

how hackers start their afternoons.

George aka Jiri Sifalda

Written by

Freelance JS developer & digital nomad. Several side-projects including e-com. Every day is just an another chance to learn and see something new!

HackerNoon.com

how hackers start their afternoons.