React Native- Theming made simple(2022)

Hello everyone. As you might have guessed from the title, nowadays every developer wants to add the theming feature to their mobile apps and is looking for the simplest and most reliable solution that does the job. Let us discuss more about this!

As you get excited to add the theming feature to your app, you will either take one of two ways:

1) Create it by yourself (usually with react native Context)

2) Install a library/package that dose the job!

  • Problem:

Of course, 90% of developers will choose the second option to save both time and focus. However, when it comes to react native, this becomes a little more complicated because most packages are either outdated or come with unnecessary features that aren't really needed in your project.

For example, NativeBase provides the option of theming; however, the theming feature is shipped with other components that you may not want in your app and can also increase the app's size.

Another example, StyledComponents library, it gives the option for theming; however, you have to adapt to a new way of styling which is just like css.

  • Solution:

I was able to create a simple and optimized way to do the same job of theming for react native by using MST (mbox state tree) behind the scenes.

Here are some of the features:

1) Similar to standard react native styling, but with additional props that can be added to make it themeable.

2) Behind the scenes, memoization has been optimized for maximum performance.

3) Easy to use + light weight + very clear

4) Can be implemented for Views + Text + Images...

Example of how it works with Text:

  • Normal way:
const DemoComponent = () => {

<Text style={DEMO_TEXT}>Hey, I am normal text</Text>

}

const DEMO_TEXT: TextStyle = {
  fontWeight: 'bold',
  fontSize: 14,
  color: 'white'
}
  • Themed way:
const DemoComponent = () => {

<Text style={apply(DEMO_TEXT)}>Hey, I am themed text</Text>

}

const DEMO_TEXT: TTextStyle = {
  fontWeight: 'bold',
  fontSize: 14,
  color: 'white',
  colorDark: 'black'
}

As can be seen above, with few simple steps we made our text themed.

Changes:

1) Instead of using the standard TextStyle type, we are using TTextStyle, which is essentially the same but has some additional properties such as colorDark, backgroundDark, and borderDark.

2) We only need to add apply method to apply our themed text style.

  • NOTICE: An option to use styleSheet for this also works!

Finally and most importantly, we need a way to switch between themes globally, this is where the appearanceHook comes in, let's take a look:

import {
  appearanceHook,
  apply,
  StyleSheet
} from '@theme'

const DemoComponent = () => {

// theme state
const [theme, setTheme] = useState(appearanceHook.activeTheme)

// theme toggle fun 
const toggleTheme = useCallback(async () => {
appearanceHook.switch(appearanceHook.activeTheme === 'dark' ? 'light' : 'dark')
setTheme(theme === 'dark' ? 'light' : 'dark')
}, [appearanceHook.activeTheme])

return (

    // button toggle 
   <Button
   text={'Switch theme'}
   onPress={toggleTheme}
   />


   // themed text with StyleSheet
   <Text style={apply(styles.DEMO_TEXT_THEMED)}>Hey, I am themed text</Text>

  // normal text with StyleSheet
   <Text style={styles.DEMO_TEXT_NORMAL}>Hey, I am normal text</Text>
)}


const styles = StyleSheet.create({
   DEMO_TEXT_THEMED: {
   fontWeight: 'bold',
   fontSize: 14,
   color: 'white',
   colorDark: 'black'
   },
   DEMO_TEXT_NORMAL: {
   fontWeight: 'bold',
   fontSize: 14,
   color: 'white',
   }

})

Currently, this theming is implemented locally and is not an npm package, if you think it is very useful and would like to have access to it as an external library let me know in the comments below! Thank you.

38