React Native - More on Custom Components
This lesson is part of a series on React Native.
Step 5 - Create a CustomText component
In the components folder, create CustomText:
import { Text } from 'react-native'
import { Colors, Fonts, Spacing } from '../Theme'
const CustomText = ({ style, title = false, ...props }) => {
let color = Colors.text
let fontSize = Fonts.medium
if(title){
fontSize = Fonts.large
color = Colors.primary
}
return (
<Text
style={[{color, fontSize, fontWeight:"bold"}, style]}
{...props}
/>
)
}
export default CustomText
Notes:
- We've added a 'title' prop (a boolean) and if true, the text will be bigger and use the primary color
Updated App.js:
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 CustomText from './components/CustomText'; ///////////////// IMPORT THIS
export default function App() {
return (
<CustomScreen>
<Image source={Logo} style={{ width: 100, height: 100, marginBottom: 20 }} />
{/* <Text style={styles.title}>Your App Name</Text> */} // REPLACE WITH (note title is true):
<CustomText title>Your App Name</CustomText>
// ADD THIS JUST TO SHOW YOU DON'T ALWAYS NEED TO USE THE CustomText
<Text>Welcome to your app!</Text>
{/* <Text style={styles.label}>Email</Text> */} // REPLACE WITH THIS:
<CustomText style={styles.label}>Email</CustomText>
<TextInput placeholder="Enter your email" style={styles.input} />
{/* <Text style={styles.label}>Password</Text> */} // REPLACE WITH THIS
<CustomText style={styles.label}>Password</CustomText>
<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>
);
}
const styles = StyleSheet.create({
// title:{ //// REMOVE
// 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,
}
});
Create a Spacer componnent
Now we'll make a simple little component that will make our lives easier....
Create Spacer.jsx in the components folder:
import { View } from 'react-native'
const Spacer = ({ width = "100%", height = 40 }) => {
return (
<View style={{ width, height }} />
)
}
export default Spacer
Import the component in App.js:
import Spacer from './components/Spacer'
Then add it under the Text element that says 'Welcome to your app!' in App.js:
<Spacer height={40} />
Create a CustomButton component
Remember that you can't really apply styles to the Button component that comes with React Native. So a custom button is usually the first component thing you create.
Create CustomButton.jsx in the components folder:
import { Pressable, StyleSheet } from 'react-native'
import { Colors} from '../Theme'
function CustomButton({ style, ...props }) {
return (
<Pressable style={[styles.btn, style]} {...props} />
)
}
const styles = StyleSheet.create({
btn: {
backgroundColor: Colors.primary,
padding: 18,
}
})
export default CustomButton
Then update App.js:
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 CustomText from './components/CustomText';
import Spacer from './components/Spacer';
import CustomButton from './components/CustomButton'; ///////////////////Import it
export default function App() {
return (
<CustomScreen>
<Image source={Logo} style={{ width: 100, height: 100, marginBottom: 20 }} />
<CustomText title>Your App Name</CustomText>
<Text>Welcome to your app!</Text>
<Spacer height={40} />
<CustomText style={styles.label}>Email</CustomText>
<TextInput placeholder="Enter your email" style={styles.input} />
<CustomText style={styles.label}>Password</CustomText>
<TextInput placeholder="Enter your password" style={styles.input} secureTextEntry />
// REMOVE THIS
{/* <View style={styles.btnContainer}>
<Button title="Submit" style={styles.btn} onPress={() => {console.log('Button pressed!')}} />
</View> */}
// ADD THIS
<CustomButton
style={{margin: 20, width: '80%'}}
onPress={() => console.log('Custom Button Pressed!')}>
<Text style={{color: 'white', textAlign: 'center', fontWeight: 'bold'}}>Custom Button</Text>
</CustomButton>
// ADD THIS JUST TO DEMO SIDE BY SIDE BUTTONS
<View style={{flexDirection:'row', columnGap: 10}}>
<CustomButton onPress={() => console.log('Custom Button Pressed!')}>
<Text style={{color: 'white', textAlign: 'center', fontWeight: 'bold'}}>Custom Button</Text>
</CustomButton>
<CustomButton onPress={() => console.log('Custom Button Pressed!')}>
<Text style={{color: 'white', textAlign: 'center', fontWeight: 'bold'}}>Custom Button</Text>
</CustomButton>
</View>
<StatusBar style="auto" />
</CustomScreen>
);
}
const styles = StyleSheet.create({
input: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
marginBottom: 10,
width: '80%',
paddingHorizontal: 10,
},
label:{
marginBottom: 5,
fontWeight: 'bold',
alignItems: 'flex-start',
width: '80%',
},
// btnContainer: { //////////// REMOVE
// width: '80%',
// marginTop: 10,
// }
});
You can style a custom button when it's being pressed. Update CustomButton.jsx:
import { Pressable, StyleSheet } from 'react-native'
import { Colors} from '../Theme'
function CustomButton({ style, ...props }) {
return (
// PASS IN A FUNCTION FOR THE STYLE PROP, IF THE PRESSED PARAM IS TRUE THEN IT'S BEING PRESSED
<Pressable
style={({ pressed }) => [styles.btn, pressed && styles.pressed, style]}
{...props}
/>
)
}
const styles = StyleSheet.create({
btn: {
backgroundColor: Colors.primary,
padding: 18,
},
/////////////////////// Add styling for the pressed state
pressed: {
opacity: 0.5
},
})
export default CustomButton