Wrap Your React Native Components

Cameron Moss
5 min readJan 20, 2017

--

Note: This post is old. I don’t think I would still say that “wraping” text components is best practice. Instead, I’ve been defining the half-dozen font styles I used in a separate file that can be imported and spread into style (or emotion) definitions as needed.

One might think that since core React Native components are classes, that they should be extended. But as Dan Abramov has stated, that’s not such a great idea. You could implement higher order components but really what you probably need is just to replace usage of certain core react-native components with something a bit more powerful. That’s where wrapping comes in.

By simply wrapping a core RN component in a bit of UI functionality you keep your code clean and also set global properties. For experienced RN developers, look through your stylesheets and find how many times you use Stylesheet to handle layout concerns. Want to get rid of that? I did. For novices, I hope this post helps you learn flexbox by giving you a tool that simplifies it considerably.

This graphic shows how it works in a nutshell. I’ll go over it later on. But I want to mention first why it is so important that you wrap certain RN core components in your own custom code.

This is just an example of one wrapped component that I happen to love using and have open-sourced. But you’ll find more often you need to wrap your own. I’ll explain.

I’ve created two published react-native apps, and after refactoring the last project, I’ve decided there are 3 three things you should definitely always wrap.

  1. Text
  2. Touchable
  3. View

To be clear, wrapping means you will be importing and using your own Text component from src instead of the one from RN. Yours will wrap that.

Text

You almost have to wrap Text for two reasons. One reason is that you don’t want to import and declare the same fontFamily in every component in your app. You want to set a font as the default for all Text components or be able to easily switch between fonts somehow.

Another reason speaks to a larger issue you need to understand about React Native UI. The fontSize is a pixel amount that will appear differently on different devices with different resolutions. This is also true about height, width, margin, padding, and absolute positioning as well. That’s why should always try to use flex for layouts when possible and if not, consider using getPixelSizeForLayoutSize whenever setting these properties. It’s a pain, but consider it reason to really try to accomplish everything with flexbox first.

For Text however, you need to avoid setting fontSize as a pixel somehow. I’ll just show you what I use, borrowing from this SO post.

my Text.js wrapper

In essence, wrapping like this is actually mapping props to styles. Some might consider it an anti-pattern, but the result is a wonderful tool for the developer who is minimally-minded. Instead of importing Text from ‘react-native’ you would instead import it from ‘/components/Text.js’ or wherever you decide to put it.

The props exposed should cover the majority of your styles, so you may not need to crate a Stylesheet entry at all.

<Text type=’bold’ fontSize={14} color=’#fff’ center transparent> 

That’s how I use it. It’s pretty clean and I know how this text will look without having to reference a stylesheet.

Touchable

There are plenty of modules out there to wrap this, though none that are all too popular , but the essential point is that Touchable(NativeFeedback, etc.) is handled differently on both iOS and Android so you shouldn’t be importing this from React Native. You can find plenty of Button implementations too, but they tend to have styles built in

View

For View I would suggest checking out my react-native-row component.

I decided on something after I took to refactoring the UI of my last app. I realized that rather than finding elements that were reusable and deserved their own declaration, I was instead finding scenes whose elements weren’t used in other scenes.

I thought of other ways of reducing clutter. I remembered having to set flexDirection:row when it was often the only property to set. I began by creating a wrapper around View to do just that. But then I noticed as many times where I had used only alignItems and justifyContents.

Sufficed to say I ended up creating a wrapper that did something I half was hoping it would do. It rendered my Stylesheet declarations unnecessary.

Let’s start with this scene. It’s a profile management screen. There aren’t any reusable components here besides the Buttons and perhaps the logo. There’s a ScrollView component that I don’t really plan to use anywhere else in the app.

So essentially the main goal of this page is to arrange elements, a lot of which are Text.

So looking at the code for the top part of the page this you can see a little mix of inline styles and Stylesheet usage. Not ideal, but the advantages of one over has never convinced me to rule one or the other out as a matter of convention.

a bit of a mess

I changed this a bit, acknowledging the sloppiness and incorrect style usage, but stuff like this happened because I never landed on a “better” way to do handle styles. But are we really declaring “styles” here anyway? Everything outside of the text styles really concerns layout.

I set out to remove the need to ask ourselves where to deal with layout styles because with flexbox, they aren’t really styles. Flexbox deserves it’s own place outside of styles because it’s so powerful, but often misunderstood.

Look what happens when we replace flexbox layout assignment with something more intuitive and concise .

pretty

Simple enough?

Note on react-native-row: Row is a View with flexDirection:’row’ and dial sets the position of all child components to the position of the number 5 on a phone dial — and flex, used here as a boolean, sets the flex property to 1.

Using react-native-row and the Text component above, I’ve moved all flexbox properties out of the style completely and made my scene more responsive.

Thoughts?

I’m no React expert, but I’ve spent a year with React Native and this is what makes sense to me. Is there a better way to implement this? Probably. Is it an anti-pattern? Maybe. I’d love to hear what people think.

--

--

Cameron Moss

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