React Native - Custom Components

This lesson is part of a series on React Native.

Step 4 - Custom Components

Create Theme.js

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

Create a CustomScreen component

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:

Updates to App.jsx:

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} />
  )
}