How to write maintainable styles in React Native
(This is gonna be a short one)
At Gamezop, we recently started writing part of our app redesign in React Native. One of the first challenges that came up was:
How to write our styles efficiently React (Native)?
The Problem
Our app uses a custom font through most of the views we have. So for each Text component that we rendered we had to write some style rules, such as
//HelloTitle.jsconst HelloTitle = ({ title }) => (
<Text style={styles.title}>Hello { title }</Text>
)const styles = StyleSheet.create({
title: {
...Platform.select({
ios: {
fontFamily: 'Gamezop',
},
android: {
fontFamily: 'gamezop',
}
})
}
})
Repeating the same code everywhere is never a good idea.
The Hacky Way
One of the proposed solutions, was to isolate the recurring styles into a single global stylesheet akin to global CSS rules. Requiring the file when and where required.
//styles.jsexport default StyleSheet.create({
title: {
...Platform.select({
ios: {
fontFamily: 'Gamezop',
},
android: {
fontFamily: 'gamezop',
}
})
}
})
Then use it like
//HelloTitle.jsimport Styles from './styles.js'const HelloTitle = ({ title }) => (
<Text style={Styles.title}>Hello { title }</Text>
)
But this approach didn’t seem to adhere to the React approach, it lacked composability.
The Solution
Higher Order Components / Custom Components
Higher Order Components are components, that take in a component and returning a component, with some changes. Higher Order Components are seen as a more functional approach to replace mixins. The same problem can be expressed more succinctly as:
//GzpText.jsconst GzpText = props => (
<Text {...props} style={[styles.font, props.style]}>
{props.children}
</Text>
)const styles = StyleSheet.create({
font: {
...Platform.select({
ios: {
fontFamily: 'Gamezop',
},
android: {
fontFamily: 'gamezop',
}
})
}
})export default GzpText
Here GzpText wraps the native Text component, to yield a custom Text component which wraps its child contents in Text components with our styles pre-applied.
This is great for its composability our HelloTitle component can simply be rewritten as
//HelloTitle.jsimport GzpText from './GzpText'const HelloTitle = ({ title }) => (
<GzpText>Hello { title }</GzpText>
)
Some follow up material regarding Higher Order Components and how they replace mixins using composition.
Feedback? Tweet me!