React Native - Custom Components
This lesson is part of a series on React Native.
Step 4 - Custom Components
Create Theme.js
- NOTE: give this file to the students so that they don't have to copy it
export const Colors = {
primary: '#6200ee',
secondary: '#03dac6',
accent: '#FF5722',
error: '#b00020',
text: '#000000',
screenBackground: '#f5f5f5',
}
export const Fonts = {
regular: 12,
medium: 16,
large: 24,
}
export const Spacing = {
small: 8,
medium: 16,
large: 24,
}
IMPORTANT TO POINT OUT
- There are lots of ways of applying themes to your app
- This may not be the best way because it can get to be really messy when your app becomes complex
- Therefore, we'll just do some very minimal global styling.
Create a CustomScreen component
- Create a components folder
- Create a file named CustomScreen.jsx
- use the rnfes shortcut to create the boilerplate code
- put this code in the file:
import { StyleSheet, Text, View } from 'react-native'
import { Colors, Fonts, Spacing } from '../Theme'
const CustomScreen = ({children, style, ...props}) => {
return (
<View style={[styles.container, style]} {...props}>
{children}
</View>
)
}
export default CustomScreen
const styles = StyleSheet.create({
container:{
backgroundColor: Colors.screenBackground,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}
})
Notes:
- We're pulling styles from the theme
- Note the props:
- children - allows us to insert elements inside this component
- style - allows us to override the default styling, we'll see this when we use the component in App.jsx
- ...props allow us to override and other props
- You can assign an array to the style prop
Updates to App.jsx:
- Make sure to show how the role prop shows up when you run the app in the browser and use the element inspector
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, TextInput, Button, Image} from 'react-native';
import Logo from './assets/icon.png';
import CustomScreen from './components/CustomScreen'; ///////////////////IMPORT THIS
export default function App() {
return (
// <View style={styles.container}> ///////////////////////////REMOVE
//The style prop shows how we can override the styles defined in the CustomScreen component if we want to
// The role prop shows how we can override any other props (because we put ...props in the custom compnent)
// You can see the 'role' prop if you run the app in the browser and use the element inspector
<CustomScreen style={{ backgroundColor: 'red' }} role="main">
<Image source={Logo} style={{ width: 100, height: 100, marginBottom: 20 }} />
<Text style={styles.title}>Your App Name</Text>
<Text style={styles.label}>Email</Text>
<TextInput placeholder="Enter your email" style={styles.input} />
<Text style={styles.label}>Password</Text>
<TextInput placeholder="Enter your password" style={styles.input} secureTextEntry />
<View style={styles.btnContainer}>
<Button title="Submit" style={styles.btn} onPress={() => {console.log('Button pressed!')}} />
</View>
<StatusBar style="auto" />
</CustomScreen>
// </View>
);
}
const styles = StyleSheet.create({
// container: { // we can remove this because it's in CustomScreen
// flex: 1,
// backgroundColor: '#fff',
// alignItems: 'center',
// justifyContent: 'center',
// },
title:{
fontSize: 24,
marginBottom: 20,
},
input: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
marginBottom: 10,
width: '80%',
paddingHorizontal: 10,
},
label:{
marginBottom: 5,
fontWeight: 'bold',
alignItems: 'flex-start',
width: '80%',
},
btnContainer: {
width: '80%',
marginTop: 10,
}
});
You can remove the {children} in the JSX of CustomScreen by making it a self-closing element (the children will automatically be applied)
const CustomScreen = ({/*children,*/ style, ...props}) => {
// make sure to remove 'children' from the params, or it won't work
return (
<View style={[styles.container, style]} {...props} />
)
}