In this article we’ll be discussing on building a robust stylesheet guideline for react native. This guideline is built with the aid of theming provided by react native elements along with Stylesheet API in react native. However at the end of this article you will see that its not just limited to react native elements at all. Along with this we’ll see how some blockers such as code separation, module resolution issues in compilation, type safety… etc. were resolved as well.
Why even bother with theming ? 🤔
Features like theming or even internationalization are common to be found in majority of the applications found in the market. (Ex: Reddit, Facebook, Messenger) Perhaps your application may not need it at this point. But if you’re planning to build a scalable application, then it will be pretty hard to integrate these features when the codebase matures with time. So, it’s convenient to plan ahead and adopt them at an early stage.
Let’s get started 🚀
We’ll start off with the typescript react native template from react native community.
npx react-native init StyleProApp --template react-native-template-typescript
Structuring your Application Matters 🧱
How you structure your codebase is opiniated & it may differ depending on the context of your application. But the general norm or a good case practice in terms of maintaining your UI is to break down your components as much as possible.
Recently I came across atomic design. Which is good to adopt because it provides flexibility, maintainability & testability in the long run.
Skipping ahead for the stylesheet ⏭️
Since we’ll be utilizing React Native Elements,
yarn add react-native-elements
Next steps are to create a theming file and pass it down as a prop into the theming provider which wraps the entire application.
But since we’re working with typescript, first will need to extend our theme type from react native element’s theme. Instead of adopting Typescript’s declaration merging method as mentioned in the official documentation’s guideline I’ve created a separate set of types.
p.s Current version of react native elements (3.4.1) doesn’t export some of its types such as Colors from core modules. They need to be imported via the dist/ directory in node modules.
Edit: For some weird reason on metro server I couldn’t split my types to a custom declaration file. So I included all the types & interfaces within the theme file.
Adding custom path alias in tsconfig.json
So, our initial theme file looks like this. Note that I have exported a hook for using theme context as well.
Then we pass this down to the theme prop in the Theme Provider.
Using theme values & separation of styles 🎨
For starters let’s just say that I need to style my progressive indicator via this approach. We’ll create a separate style file and build a custom hook like function for styling.
Then using this inside your component is a bit simple.
Module Resolution ✔️
Although you may be able to fix the typescript errors that occur for importing contents from path aliases via tsconfig.json, metro server will still throw errors for unresolved paths. To fix this what you need to do is add a dev dependency.
yarn add --dev babel-plugin-module-resolver
Then edit your babel.config.js,
Although above approach is mainly utilizing react-native-element’s ThemeProvider, you can build your own ThemeProvider using React’s Context API & plug it in the same manner. So its just a matter of spending a little more time on writing your own context provider & context consumer.
Good Case Practices in managing your styles ✍️
It’s very important for your application to be responsive across majority of devices. Using flexbox layout at almost all the time and using relative values for certain styling properties (Ex: top: 20%, etc.) are couple of good choices for this. Refer the guideline provided by react native documents for this.
However, in certain scenarios like defining font sizes or defining fixed margin values you will need to make sure that they are scaled depending on the device pixel ratio. A good library that will help to achieve this is react-native-size-matters which is a peer dependency of react native elements.
The entire code for above is available in the following work in progress repository.