DEV Community

Cover image for React Native- Upcoming Theming library(2022)
Karam Jammal
Karam Jammal

Posted on • Updated on

React Native- Upcoming Theming library(2022)

GitHub Link:

https://github.com/KJA-Tsx/theme-csx

Dev link

https://dev.to/kjacsx/react-native-theming-made-easy2022-479c


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'
}
Enter fullscreen mode Exit fullscreen mode
  • Themed way:
const DemoComponent = () => {

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

}

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

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 T 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:


// Styles
import { StyleSheet, T, appearanceHook} from "theme-csx";

// Components 
import { Text, View } from 'react-native';
import { Button } from '@components/atoms';

const DemoComponent = () => {

// Theme switch
const switchTheme = () => {
appearanceHook.switch(appearanceHook.activeTheme === 'dark' ? 'light' : 'dark')
}

return (
   <View style={T(styles.THEMED_CONTAINER)}>

      <Text style={styles.NORMAL_TEXT}>Hey, I am normal text</Text>

      <Text style={T(styles.THEMED_TEXT)}>Hey, I am themed text</Text>

      <Button text={'Switch theme'} onPress={switchTheme} />

   </View>
)}


const styles = StyleSheet.create({
    THEMED_CONTAINER: {
    flex: 1,
    backgroundColor: 'white',
    backgroundDark: 'gray', // backgroundDark porp was added to make it themeable
    alignItems: 'center',
    justifyContent: 'center',
   },
   NORMAL_TEXT: {
   fontWeight: 'bold',
   fontSize: 14,
   color: 'green',
   },
   THEMED_TEXT: {
   fontWeight: 'bold',
   fontSize: 14,
   color: 'black',
   colorDark: 'white'  // colorDark porp was added to make it themeable
   },
})

Enter fullscreen mode Exit fullscreen mode

Discussion (0)