OhSnap! Manage Global Styles In React Native
Tags: reactnative, webdev, javascript, beginners
Published: 2021-05-24 08:20:30

*The "OhSnap!" series explores bite-sized tips that you can apply today.*

---


##Introduction 
One of the big adjustments I had to make when using React Native, is not relying on CSS. 

Sure, there are still "CSS-like" properties that use the JS-based `StyleSheet` method, but they are not the same. 

For example, since everything is locally scoped, we can’t easily set global styles. 

####Well, not quite... 

Here are two ways to handle global styles that are actually pretty simple, yet powerful. 

---


##Method A: Custom Styled Component

Using a standard React pattern, we will create a custom component for the element we want to style globally. 

Within this component, we can set default styles and also use props to override those styles. 

Then we can import and use this component anywhere in our project. If the styles need to change, only that component needs to be updated. 

####For example:

* **`<HeaderOne />`** could contain a bold `<Text>` element with a large font size. 

* **`<BodyText />`** could contain a smaller, dark grey `<Text>` element. 

* **`<PrimaryButton />`** could contain a `<TouchableOpacity>` element with a green background and uppercase text.




> *(This is a very similar concept to the [styled-componets](https://styled-components.com/) package.)*

Aright! Enough talk. Let's see how it actually looks and set up a styled button we can use globally. 


####Step 1: Create base `<PrimaryButton />` component 

Our component should accept props and import some standard React Native default components to create the base structure & functionality.

```JSX
import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';


const PrimaryButton = props => {
  return (
    <TouchableOpacity 
      onPress={() => props.pressHandler}
    >
     <Text>{props.title}</Text>
    </TouchableOpacity>
  );
};

export default PrimaryButton;
```

####Step 2: Add base styles

Using the `StyleSheet` method from React Native, set up some base styles for this button.

```JSX
import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';


const PrimaryButton = props => {
  return (
    <TouchableOpacity 
      style={styles.btnContainer} 
      onPress={() => props.pressHandler}
    >
     <Text style={styles.text}>{props.title}</Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
    btnContainer: {
        paddingVertical: 3,
        paddingHorizontal: 10
        backgroundColor: 'green',
        justifyContent: 'center',
    },
    text: {
      color: 'white',
      fontSize: 20,
    }, 
});

export default PrimaryButton;
```

####Step 3: Spread local styles & prop styles

Use the spread operator to add all current styles and then any custom styles being passed in via props. This will allow additional styles to be added/overwritten. 

```JSX
import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';


const PrimaryButton = props => {
  return (
    <TouchableOpacity 
      style={{...styles.btnContainer, ...props.containerStyle}}
      onPress={() => props.pressHandler}
    >
     <Text 
       style={{...styles.text, ...props.textStyle}}
     >
      {props.title}
     </Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
    btnContainer: {
        paddingVertical: 3,
        paddingHorizontal: 10
        backgroundColor: 'green',
        justifyContent: 'center',
    },
    text: {
      color: 'white',
      fontSize: 20,
    }, 
});

export default PrimaryButton;
```

####Step 4: Use `<PrimaryButton />` anywhere in the project

Note how we are passing in a custom margin, via props. This will get applied to the button, in addition to the default local style we set up already.  

```JSX
import React from 'react';
import { StyleSheet, Text, View} from 'react-native';
import PrimaryButton from './components/PrimaryButton'


const ContactScreen = props => {
  return (
   <View>
    <Text>Contact Us</Text>
    •••
    <PrimaryButton 
      title="Submit"
      pressHandler={someCoolFunction}
      containerStyle={styles.btn}
      textStyle={styles.title}
    />
   </View>
  );
};

const styles = StyleSheet.create({
    btn: {
        marginTop: 10,
    },
    btnTitle: {
      color: 'grey',
    }, 
});

export default ContactScreen;
```

---


##Method B: Export Global Object
This next method can either be used instead of custom components or in conjunction with it. 

The idea to store *values* for CSS properties inside of objects or variables that are exported from global files.

Let's take the example of how to work with colors. Imagine having to change the "Primary" brand color from blue to green. With the below method you just need to update that color in one file. 

####Step 1: Create a global styles folder

In the root of the `src` directory create a new folder called `styles` and add a new file called `colors.js`. 

```
/src
|—— /styles
    |—— colors.js
```

####Step 2: Add property values. 

Create and export an object within the colors file that holds the values

```JS
export default {
  primary: '#FFBB0B',
  primaryLight: '#FFDF8E',
  primaryDark: '#CB9303',
  secondary: '#63321C',
  secondaryLight: '#735243',
  secondaryDark: '#170F0C',
};
```

####Step 3: Import and use the Colors file. 
Now you can go to any file in your project and reference the colors you have set up in step 2 on any acceptable property.

If any time your brand colors change, these files will update automatically! 


```JSX
import React from 'react';
import { StyleSheet, Text, View} from 'react-native';
import colors from '../styles/colors'; <-----------


const ContactScreen = props => {
  return (
   <View style={styles.header}>
    <Text style={styles.headline}>Contact Us</Text>
   </View>
  );
};

const styles = StyleSheet.create({
    header: {
      flex: 1,
      backgroundColor: colors.secondaryLight, <-----------
    },
    headline: {
        color: colors.primary, <-----------
    },
});

export default ContactScreen;
```

---

*Thumbnail designed with [Adobe Photoshop](https://www.adobe.com/products/photoshop.html)*