Why you don’t need Styled-Components in a React Native app.

Cameron Moss
4 min readFeb 1, 2017

--

Note: Styled Components looks to be a lot more powerful than it was when I wrote this. I use glamorous-native myself. If you are new to react-native styles this article may still prove insightful.

2017 is the year when we finally get styles right. This, prophesied by Glenn Maddern in his excellent talk at ColdFront16, seems to be why Max Stoiber and he created the super popular Styled Components project. While Styled seems to be making inroads in the web React community, my aim here is to evaluate it’s viability in React Native.

I’ve been refactoring the Hyr React-Native app a lot lately and I decided to attempt a complete conversion of my stylesheet styles to Styled. Here’s what I discovered:

Object Styles vs. Template Literals

Styled Components are awesome for the web because, among other things, template literals allow the use of variables in styles.

let size = someChangingCondition ? 30 : 14;const UContainer = styled.View`
height: ${size};
width: ${size};
border-radius: ${size/2};
justify-content: center;
align-items: center;
`;
<UContainer/>

But in React Native you just use objects for styles so the same thing:

let size = someChangingCondition ? 30 : 14;const styles = {
uContainer: {
height: size,
width: size,
border-radius: size/2,
justify-content: "center",
align-items: "center",
}
}
<View styles={styles.uContainer} />

But wait! Why not just make an Object-Styled Component?

let Styled = {}

const StyledComponent = (Component) => (styles) => (props) => {
const {
styles: inlineStyles,
children,
...otherProps,
} = props
return(
<Component style={[styles, inlineStyles]} {...otherProps}>
{children}
</Component>
)
};

Styled.View = StyledComponent(View)

And… done?

But there’s a catch! You don’t want to just pass styles this way because they aren’t cached. You’re going to be sending a lot of static styles across the bridge to the native UI component on every render. React Native takes care of this with Stylesheet API by creating and supplying integers that reference a cached style definition. So when you use styles.myContainer you actually returning an integer referencing the style definition in Stylesheet.create(). Console log it if you don’t believe me!

Therefore, we need something better. Fortunately there’s the Glamorous library. With that you can do the following and behind the scenes, the library is actually doing the caching for you:

let size = someChangingCondition ? 30 : 14;const UContainer = glamorous.view({
height: size,
width: size,
border-radius: size/2,
justify-content: "center",
align-items: "center",
})
<UContainer/>

Best of both worlds?

Once I had object styles back I found I still had issues. What surprised me the most about Styled was the fact that one of the authors actually pinpointed the exact solution I was starting to come to with my styles.

“I think the way to build reusable components is to only set padding and that layout becomes a separate class of components… [with] the parent element in control of it’s children.”

-Glenn Maddern: The Future of Reusable CSS

I can see the benefit Styled in terms of cleaning up the JSX, but is it really accomplishing what Maddern says here? With Styled Components are you not still left to create this set of layout components, perhaps globally and perhaps on a file-level basis.

Naming things is bad. Copy and pasting is good.

-Ryan Florence

Are we naming things with Styled? Yes. Can you easily copy and paste a Styled Component? I’d say for the most part; however, it’s not always just the styled definition that needs to be copied, it’s also a chunk of the UI that you decide to refactor into a component file. So in that respect…

Separate your Layout Styles from other Styles

Layout should be defined in or be easily inferred from the name of the component JSX instance itself. Layout is only readable in relation to its context. So my advice is to stick to a UI layout component library like shoutem or pass layout styles as props. Avoid putting layout styles in Styled definitions, where you lose the context (being at the top of the file). Colors and other styles however, I’m fine to extract away. So the ideal situation for me is this:

import { Styled } from react-native-row

const GreenRow = Styled.Row({
backgroundColor: "green"
})

<GreenRow flex={2}>
<Text>Hi</Text>
</GreenRow>

In essence, make all layout styles props, and leave the rest to Styled Component definitions. Or just use inline styles every once and a while. You’d be surprised how much of styles is just layout.

React Native a lot to teach the web world about styles. The ease of flexbox usage is another huge advantage. Who knows — perhaps soon object styles will be the standard with which we transpile to css.

--

--

Cameron Moss

all things js, react-native + redux, foster parenting, social justice