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 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.
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.
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.
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.
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
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!
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
Top comments (1)
Starting my first major React Native project today and this was a huge help in laying the foundation for global styling and reusable components. Thank you so much!