Lesson 3 of 8

Core Components & APIs

View, Text, Image, ScrollView, FlatList, and essential native components

Core Components Overview

React Native provides a set of core components that map directly to native platform views. These are the building blocks for your mobile UI.

View - The Container Component

import { View, StyleSheet } from 'react-native';

// View is the most fundamental component
// It's like a div in web development
function LayoutExample() {
  return (
    <View style={styles.container}>
      <View style={styles.box1} />
      <View style={styles.box2} />
      <View style={styles.box3} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'space-around',
    alignItems: 'center',
    padding: 20,
  },
  box1: { width: 60, height: 60, backgroundColor: '#3498db' },
  box2: { width: 60, height: 60, backgroundColor: '#e74c3c' },
  box3: { width: 60, height: 60, backgroundColor: '#2ecc71' },
});

Text - Displaying Text

import { Text, StyleSheet } from 'react-native';

function TextExample() {
  return (
    <View>
      {/* Basic text */}
      <Text style={styles.title}>Hello, React Native!</Text>
      
      {/* Nested text for inline styling */}
      <Text style={styles.paragraph}>
        This is <Text style={styles.bold}>bold</Text> and 
        this is <Text style={styles.italic}>italic</Text>.
      </Text>
      
      {/* Text with line limit */}
      <Text numberOfLines={2} ellipsizeMode="tail">
        This is a very long text that will be truncated 
        after two lines with an ellipsis at the end...
      </Text>
      
      {/* Selectable text */}
      <Text selectable>You can select this text</Text>
      
      {/* Linked text */}
      <Text 
        style={styles.link}
        onPress={() => Linking.openURL('https://reactnative.dev')}
      >
        Tap to open link
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
  },
  paragraph: {
    fontSize: 16,
    lineHeight: 24,
    color: '#666',
  },
  bold: { fontWeight: 'bold' },
  italic: { fontStyle: 'italic' },
  link: { color: '#007AFF', textDecorationLine: 'underline' },
});

Image - Displaying Images

import { Image, StyleSheet } from 'react-native';

function ImageExample() {
  return (
    <View>
      {/* Local image (require) */}
      <Image 
        source={require('./assets/logo.png')}
        style={styles.localImage}
      />
      
      {/* Remote image (uri) - must specify dimensions */}
      <Image
        source={{ uri: 'https://picsum.photos/200/200' }}
        style={styles.remoteImage}
      />
      
      {/* Image with resize modes */}
      <Image
        source={{ uri: 'https://picsum.photos/400/200' }}
        style={styles.coverImage}
        resizeMode="cover"  // cover, contain, stretch, center
      />
      
      {/* Background image */}
      <ImageBackground
        source={{ uri: 'https://picsum.photos/400/300' }}
        style={styles.backgroundImage}
      >
        <Text style={styles.overlayText}>Text over image</Text>
      </ImageBackground>
      
      {/* Image with loading placeholder */}
      <Image
        source={{ uri: 'https://picsum.photos/200/200' }}
        style={styles.remoteImage}
        defaultSource={require('./assets/placeholder.png')}
        onLoad={() => console.log('Image loaded')}
        onError={(e) => console.log('Error:', e.nativeEvent.error)}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  localImage: { width: 100, height: 100 },
  remoteImage: { width: 200, height: 200, borderRadius: 10 },
  coverImage: { width: '100%', height: 200 },
  backgroundImage: {
    width: '100%',
    height: 200,
    justifyContent: 'center',
    alignItems: 'center',
  },
  overlayText: { color: '#fff', fontSize: 24, fontWeight: 'bold' },
});

ScrollView - Scrollable Container

import { ScrollView, View, Text, StyleSheet } from 'react-native';

function ScrollViewExample() {
  return (
    <ScrollView 
      style={styles.scrollView}
      contentContainerStyle={styles.contentContainer}
      showsVerticalScrollIndicator={false}
    >
      {[...Array(20)].map((_, i) => (
        <View key={i} style={styles.item}>
          <Text>Item {i + 1}</Text>
        </View>
      ))}
    </ScrollView>
  );
}

// Horizontal ScrollView
function HorizontalScrollExample() {
  return (
    <ScrollView 
      horizontal
      showsHorizontalScrollIndicator={false}
      pagingEnabled  // Snap to pages
    >
      {[...Array(5)].map((_, i) => (
        <View key={i} style={styles.page}>
          <Text>Page {i + 1}</Text>
        </View>
      ))}
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  scrollView: { flex: 1 },
  contentContainer: { padding: 20 },
  item: {
    height: 80,
    backgroundColor: '#f0f0f0',
    marginBottom: 10,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8,
  },
  page: {
    width: 300,
    height: 200,
    backgroundColor: '#3498db',
    justifyContent: 'center',
    alignItems: 'center',
    marginRight: 10,
  },
});

⚠️ ScrollView vs FlatList

ScrollView renders all children at once. Use for small, fixed content.
FlatList renders items lazily (virtualized). Use for long lists of data.

FlatList - Optimized Lists

import { FlatList, View, Text, StyleSheet } from 'react-native';

const DATA = [
  { id: '1', title: 'First Item' },
  { id: '2', title: 'Second Item' },
  { id: '3', title: 'Third Item' },
  // ... many more items
];

function FlatListExample() {
  const renderItem = ({ item, index }) => (
    <View style={styles.item}>
      <Text style={styles.title}>{item.title}</Text>
    </View>
  );

  return (
    <FlatList
      data={DATA}
      renderItem={renderItem}
      keyExtractor={(item) => item.id}
      
      // Header and Footer
      ListHeaderComponent={<Text style={styles.header}>Header</Text>}
      ListFooterComponent={<Text style={styles.footer}>Footer</Text>}
      
      // Empty state
      ListEmptyComponent={<Text>No items to display</Text>}
      
      // Pull to refresh
      refreshing={false}
      onRefresh={() => console.log('Refreshing...')}
      
      // Infinite scroll
      onEndReached={() => console.log('Load more...')}
      onEndReachedThreshold={0.5}
      
      // Performance
      initialNumToRender={10}
      maxToRenderPerBatch={10}
      windowSize={5}
      
      // Separators
      ItemSeparatorComponent={() => <View style={styles.separator} />}
    />
  );
}

const styles = StyleSheet.create({
  item: {
    backgroundColor: '#f9f9f9',
    padding: 20,
  },
  title: { fontSize: 18 },
  header: { fontSize: 24, padding: 20 },
  footer: { fontSize: 16, padding: 20, color: '#888' },
  separator: { height: 1, backgroundColor: '#eee' },
});

SectionList - Grouped Lists

import { SectionList, View, Text, StyleSheet } from 'react-native';

const SECTIONS = [
  {
    title: 'Fruits',
    data: ['Apple', 'Banana', 'Orange'],
  },
  {
    title: 'Vegetables',
    data: ['Carrot', 'Broccoli', 'Spinach'],
  },
];

function SectionListExample() {
  return (
    <SectionList
      sections={SECTIONS}
      keyExtractor={(item, index) => item + index}
      renderItem={({ item }) => (
        <View style={styles.item}>
          <Text>{item}</Text>
        </View>
      )}
      renderSectionHeader={({ section: { title } }) => (
        <View style={styles.header}>
          <Text style={styles.headerText}>{title}</Text>
        </View>
      )}
      stickySectionHeadersEnabled={true}
    />
  );
}

const styles = StyleSheet.create({
  item: { padding: 15, backgroundColor: '#fff' },
  header: { padding: 10, backgroundColor: '#f0f0f0' },
  headerText: { fontSize: 16, fontWeight: 'bold' },
});

Touchable Components

import { 
  TouchableOpacity, 
  TouchableHighlight,
  TouchableWithoutFeedback,
  Pressable,
  Text, 
  View 
} from 'react-native';

function TouchableExample() {
  return (
    <View>
      {/* TouchableOpacity - Fades on press */}
      <TouchableOpacity 
        onPress={() => console.log('Pressed!')}
        activeOpacity={0.7}
        style={styles.button}
      >
        <Text>TouchableOpacity</Text>
      </TouchableOpacity>
      
      {/* TouchableHighlight - Darkens on press */}
      <TouchableHighlight
        onPress={() => console.log('Pressed!')}
        underlayColor="#ddd"
        style={styles.button}
      >
        <Text>TouchableHighlight</Text>
      </TouchableHighlight>
      
      {/* Pressable - Modern API with more control */}
      <Pressable
        onPress={() => console.log('Pressed!')}
        onLongPress={() => console.log('Long pressed!')}
        onPressIn={() => console.log('Press in')}
        onPressOut={() => console.log('Press out')}
        style={({ pressed }) => [
          styles.button,
          { opacity: pressed ? 0.7 : 1 }
        ]}
      >
        {({ pressed }) => (
          <Text>{pressed ? 'Pressed!' : 'Pressable'}</Text>
        )}
      </Pressable>
    </View>
  );
}

TextInput - User Input

import { TextInput, View, StyleSheet, useState } from 'react-native';

function TextInputExample() {
  const [text, setText] = useState('');
  const [password, setPassword] = useState('');

  return (
    <View style={styles.container}>
      {/* Basic text input */}
      <TextInput
        style={styles.input}
        value={text}
        onChangeText={setText}
        placeholder="Enter text..."
        placeholderTextColor="#999"
      />
      
      {/* Password input */}
      <TextInput
        style={styles.input}
        value={password}
        onChangeText={setPassword}
        placeholder="Password"
        secureTextEntry
      />
      
      {/* Multiline input */}
      <TextInput
        style={[styles.input, styles.multiline]}
        multiline
        numberOfLines={4}
        placeholder="Enter description..."
        textAlignVertical="top"
      />
      
      {/* Keyboard types */}
      <TextInput
        style={styles.input}
        keyboardType="email-address"  // email, numeric, phone-pad, etc.
        autoCapitalize="none"
        autoCorrect={false}
        placeholder="Email"
      />
      
      {/* With return key handling */}
      <TextInput
        style={styles.input}
        returnKeyType="search"
        onSubmitEditing={() => console.log('Search submitted')}
        placeholder="Search..."
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { padding: 20 },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    padding: 12,
    fontSize: 16,
    marginBottom: 16,
  },
  multiline: {
    height: 100,
  },
});

Component Quick Reference

Component Web Equivalent Use For
View div Container, layout
Text p, span, h1-h6 All text content
Image img Images
ScrollView div with overflow Small scrollable content
FlatList ul/ol (virtualized) Large lists
Pressable button Touch interactions
TextInput input, textarea User text input