DailyDevDiet

logo - dailydevdiet

Learn. Build. Innovate. Elevate your coding skills with dailydevdiet!

Chapter 34: React Native Basics

React Native Basics

Introduction

React Native is a popular framework developed by Facebook that allows developers to build mobile applications using React and JavaScript. The beauty of React Native lies in its “learn once, write anywhere” philosophy – if you know React, you can leverage that knowledge to build native mobile apps for both iOS and Android platforms. Let’s learn the React Native basics in the coming lines.

What is React Native?

React Native is an open-source mobile application framework that enables developers to use React along with native platform capabilities. Unlike hybrid mobile apps that run in a WebView, React Native apps compile to native code, providing better performance and a more authentic user experience.

Key Features of React Native

  1. Cross-Platform Development: Write once, run on both iOS and Android
  2. Native Performance: Compiles to native code for optimal performance
  3. Hot Reloading: See changes instantly without rebuilding the entire app
  4. Large Community: Extensive ecosystem and community support
  5. Code Reusability: Share code between web and mobile applications
  6. Native Modules: Access to device-specific features through native modules

React vs React Native: Key Differences

Component Differences

React (Web)React Native
<div><View>
<span>, <p><Text>
<img><Image>
<input><TextInput>
<button><TouchableOpacity>

Styling Differences

React Native uses a subset of CSS properties and implements styling through JavaScript objects:

// React (Web) - CSS
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #f0f0f0;
}

// React Native - StyleSheet
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f0f0f0',
  },
});

Setting Up React Native Development Environment

Prerequisites

  1. Node.js (version 12 or higher)
  2. React Native CLI or Expo CLI
  3. Android Studio (for Android development)
  4. Xcode (for iOS development – macOS only)

Installation Options

Option 1: Expo CLI (Recommended for Beginners)

npm install -g expo-cli
expo init MyFirstApp
cd MyFirstApp
expo start

Option 2: React Native CLI

npm install -g @react-native-community/cli
npx react-native init MyFirstApp
cd MyFirstApp

For Android:
npx react-native run-android

For iOS:
npx react-native run-ios

Basic React Native Components

View Component

The View component is the fundamental building block, similar to div in HTML:

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

const BasicView = () => {
  return (
    <View style={styles.container}>
      <View style={styles.box} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  box: {
    width: 100,
    height: 100,
    backgroundColor: 'blue',
  },
});

export default BasicView;

Text Component

All text must be wrapped in a Text component:

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

const TextExample = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hello React Native!</Text>
      <Text style={styles.subtitle}>This is a subtitle</Text>
      <Text style={styles.body}>
        This is body text that can span multiple lines and
        will wrap automatically based on the container width.
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  subtitle: {
    fontSize: 18,
    color: '#666',
    marginBottom: 15,
  },
  body: {
    fontSize: 16,
    lineHeight: 24,
  },
});

export default TextExample;

Image Component

Display images from various sources:

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

const ImageExample = () => {
  return (
    <View style={styles.container}>
      {/* Local Image */}
      <Image
        source={require('./assets/logo.png')}
        style={styles.localImage}
      />
     
      {/* Network Image */}
      <Image
        source={{uri: 'https://example.com/image.jpg'}}
        style={styles.networkImage}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    padding: 20,
  },
  localImage: {
    width: 100,
    height: 100,
    marginBottom: 20,
  },
  networkImage: {
    width: 200,
    height: 150,
    resizeMode: 'cover',
  },
});

export default ImageExample;

Handling User Input

TextInput Component

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

const InputExample = () => {
  const [text, setText] = useState('');
  const [email, setEmail] = useState('');

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Name:</Text>
      <TextInput
        style={styles.input}
        value={text}
        onChangeText={setText}
        placeholder="Enter your name"
      />
     
      <Text style={styles.label}>Email:</Text>
      <TextInput
        style={styles.input}
        value={email}
        onChangeText={setEmail}
        placeholder="Enter your email"
        keyboardType="email-address"
        autoCapitalize="none"
      />
     
      <Text style={styles.output}>
        Hello {text}, your email is {email}
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  label: {
    fontSize: 16,
    fontWeight: 'bold',
    marginTop: 20,
    marginBottom: 5,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    padding: 10,
    borderRadius: 5,
    fontSize: 16,
  },
  output: {
    marginTop: 20,
    fontSize: 16,
    color: '#333',
  },
});

export default InputExample;

Touchable Components

React Native provides several components for handling touch interactions:

import React from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  TouchableHighlight,
  TouchableWithoutFeedback,
  Alert,
  StyleSheet
} from 'react-native';

const TouchableExample = () => {
  const handlePress = (type) => {
    Alert.alert('Pressed!', `You pressed the ${type} button`);
  };

  return (
    <View style={styles.container}>
      <TouchableOpacity
        style={styles.button}
        onPress={() => handlePress('TouchableOpacity')}
      >
        <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>

      <TouchableHighlight
        style={styles.button}
        onPress={() => handlePress('TouchableHighlight')}
        underlayColor="#0056b3"
      >
        <Text style={styles.buttonText}>TouchableHighlight</Text>
      </TouchableHighlight>

      <TouchableWithoutFeedback
        onPress={() => handlePress('TouchableWithoutFeedback')}
      >
        <View style={styles.button}>
          <Text style={styles.buttonText}>TouchableWithoutFeedback</Text>
        </View>
      </TouchableWithoutFeedback>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    padding: 20,
  },
  button: {
    backgroundColor: '#007bff',
    padding: 15,
    borderRadius: 5,
    marginVertical: 10,
    alignItems: 'center',
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

export default TouchableExample;

Lists in React Native

FlatList Component

For rendering large lists efficiently:

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

const ListExample = () => {
  const data = [
    { id: '1', name: 'Apple', color: 'Red' },
    { id: '2', name: 'Banana', color: 'Yellow' },
    { id: '3', name: 'Orange', color: 'Orange' },
    { id: '4', name: 'Grape', color: 'Purple' },
    { id: '5', name: 'Kiwi', color: 'Green' },
  ];

  const renderItem = ({ item }) => (
    <View style={styles.item}>
      <Text style={styles.itemName}>{item.name}</Text>
      <Text style={styles.itemColor}>{item.color}</Text>
    </View>
  );

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Fruit List</Text>
      <FlatList
        data={data}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
        showsVerticalScrollIndicator={false}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  item: {
    backgroundColor: '#f9f9f9',
    padding: 15,
    marginVertical: 5,
    borderRadius: 5,
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  itemName: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  itemColor: {
    fontSize: 16,
    color: '#666',
  },
});

export default ListExample;

Styling in React Native

StyleSheet API

React Native uses the StyleSheet API for styling:

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

const StylingExample = () => {
  return (
    <View style={styles.container}>
      <View style={styles.header}>
        <Text style={styles.headerText}>Header</Text>
      </View>
     
      <View style={styles.content}>
        <Text style={styles.contentText}>Content Area</Text>
      </View>
     
      <View style={[styles.box, styles.redBox]}>
        <Text style={styles.boxText}>Red Box</Text>
      </View>
     
      <View style={[styles.box, styles.blueBox]}>
        <Text style={styles.boxText}>Blue Box</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  header: {
    backgroundColor: '#333',
    padding: 20,
    alignItems: 'center',
  },
  headerText: {
    color: 'white',
    fontSize: 20,
    fontWeight: 'bold',
  },
  content: {
    flex: 1,
    padding: 20,
    justifyContent: 'center',
    alignItems: 'center',
  },
  contentText: {
    fontSize: 18,
    marginBottom: 20,
  },
  box: {
    width: 100,
    height: 100,
    margin: 10,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 10,
  },
  redBox: {
    backgroundColor: 'red',
  },
  blueBox: {
    backgroundColor: 'blue',
  },
  boxText: {
    color: 'white',
    fontWeight: 'bold',
  },
});

export default StylingExample;

Navigation in React Native

React Navigation

Install React Navigation:
npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context

For stack navigation:
npm install @react-navigation/stack
npm install react-native-gesture-handler

Basic navigation setup:
import React from 'react';
const HomeScreen = ({ navigation }) => {
  return (
    <View style={styles.screen}>
      <Text style={styles.title}>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details', { name: 'John Doe' })}
      />
    </View>
  );
};

const DetailsScreen = ({ route, navigation }) => {
  const { name } = route.params;
 
  return (
    <View style={styles.screen}>
      <Text style={styles.title}>Details Screen</Text>
      <Text style={styles.text}>Hello, {name}!</Text>
      <Button
        title="Go Back"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
};

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  text: {
    fontSize: 18,
    marginBottom: 20,
  },
});

export default App;

State Management in React Native

React Native uses the same state management concepts as React:

import React, { useState, useEffect } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

const CounterApp = () => {
  const [count, setCount] = useState(0);
  const [isRunning, setIsRunning] = useState(false);

  useEffect(() => {
    let interval;
    if (isRunning) {
      interval = setInterval(() => {
        setCount(prevCount => prevCount + 1);
      }, 1000);
    }
    return () => clearInterval(interval);
  }, [isRunning]);

  const handleStart = () => setIsRunning(true);
  const handleStop = () => setIsRunning(false);
  const handleReset = () => {
    setCount(0);
    setIsRunning(false);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.counter}>{count}</Text>
     
      <View style={styles.buttonContainer}>
        <Button
          title={isRunning ? "Stop" : "Start"}
          onPress={isRunning ? handleStop : handleStart}
        />
        <Button title="Reset" onPress={handleReset} />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5f5',
  },
  counter: {
    fontSize: 48,
    fontWeight: 'bold',
    marginBottom: 40,
  },
  buttonContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    width: '60%',
  },
});

export default CounterApp;

Platform-Specific Code

Handle platform differences using the Platform API:

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

const PlatformExample = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>
        Running on: {Platform.OS}
      </Text>
     
      <View style={styles.platformBox}>
        <Text style={styles.platformText}>
          {Platform.OS === 'ios' ? 'iOS Specific Feature' : 'Android Specific Feature'}
        </Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  text: {
    fontSize: 18,
    marginBottom: 20,
  },
  platformBox: {
    padding: 20,
    backgroundColor: Platform.OS === 'ios' ? '#007AFF' : '#4CAF50',
    borderRadius: 10,
  },
  platformText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

// Platform-specific styles
const platformStyles = StyleSheet.create({
  container: {
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.25,
        shadowRadius: 4,
      },
      android: {
        elevation: 5,
      },
    }),
  },
});

export default PlatformExample;

Debugging React Native Apps

Debug Tools and Techniques

  1. React Native Debugger: Standalone debugging tool
  2. Chrome Developer Tools: For JavaScript debugging
  3. Flipper: Desktop debugging platform by Facebook
  4. Console Logging: Use console.log() for quick debugging
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';

const DebugExample = () => {
  useEffect(() => {
    console.log('Component mounted');
    console.warn('This is a warning');
    console.error('This is an error for testing');
   
    // Debug network requests
    fetch('https://jsonplaceholder.typicode.com/posts/1')
      .then(response => response.json())
      .then(data => {
        console.log('API Response:', data);
      })
      .catch(error => {
        console.error('API Error:', error);
      });
  }, []);

  return (
    <View>
      <Text>Check the debugger console for logs</Text>
    </View>
  );
};

export default DebugExample;

Best Practices for React Native Development

Performance Optimization

  1. Use FlatList for large datasets
  2. Optimize images – use appropriate formats and sizes
  3. Minimize re-renders – use React.memo, useMemo, useCallback
  4. Remove console statements in production builds

Code Organization

src/

├── components/

│   ├── common/

│   └── screens/

├── navigation/

├── services/

├── utils/

├── styles/

└── constants/

Error Handling

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

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    console.log('Error caught by boundary:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <View style={styles.errorContainer}>
          <Text style={styles.errorText}>Something went wrong.</Text>
        </View>
      );
    }

    return this.props.children;
  }
}

const styles = StyleSheet.create({
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  errorText: {
    fontSize: 18,
    color: 'red',
  },
});

export default ErrorBoundary;

Complete Example: Todo App

Here’s a simple Todo app demonstrating various React Native concepts:

import React, { useState } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  FlatList,
  Alert,
  StyleSheet,
} from 'react-native';

const TodoApp = () => {
  const [todos, setTodos] = useState([]);
  const [inputText, setInputText] = useState('');

  const addTodo = () => {
    if (inputText.trim() === '') {
      Alert.alert('Error', 'Please enter a todo item');
      return;
    }

    const newTodo = {
      id: Date.now().toString(),
      text: inputText.trim(),
      completed: false,
    };

    setTodos([...todos, newTodo]);
    setInputText('');
  };

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id) => {
    Alert.alert(
      'Delete Todo',
      'Are you sure you want to delete this todo?',
      [
        { text: 'Cancel', style: 'cancel' },
        { text: 'Delete', onPress: () => setTodos(todos.filter(todo => todo.id !== id)) },
      ]
    );
  };

  const renderTodo = ({ item }) => (
    <View style={styles.todoItem}>
      <TouchableOpacity
        style={styles.todoText}
        onPress={() => toggleTodo(item.id)}
      >
        <Text style={[
          styles.todoTextContent,
          item.completed && styles.completedText
        ]}>
          {item.text}
        </Text>
      </TouchableOpacity>
     
      <TouchableOpacity
        style={styles.deleteButton}
        onPress={() => deleteTodo(item.id)}
      >
        <Text style={styles.deleteButtonText}>Delete</Text>
      </TouchableOpacity>
    </View>
  );

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Todo App</Text>
     
      <View style={styles.inputContainer}>
        <TextInput
          style={styles.input}
          value={inputText}
          onChangeText={setInputText}
          placeholder="Enter a new todo"
          returnKeyType="done"
          onSubmitEditing={addTodo}
        />
        <TouchableOpacity style={styles.addButton} onPress={addTodo}>
          <Text style={styles.addButtonText}>Add</Text>
        </TouchableOpacity>
      </View>

      <FlatList
        data={todos}
        renderItem={renderTodo}
        keyExtractor={(item) => item.id}
        style={styles.todoList}
        showsVerticalScrollIndicator={false}
      />

      <Text style={styles.summary}>
        Total: {todos.length} | Completed: {todos.filter(t => t.completed).length}
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
    padding: 20,
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 30,
    color: '#333',
  },
  inputContainer: {
    flexDirection: 'row',
    marginBottom: 20,
  },
  input: {
    flex: 1,
    borderWidth: 1,
    borderColor: '#ddd',
    padding: 12,
    borderRadius: 8,
    fontSize: 16,
    backgroundColor: 'white',
  },
  addButton: {
    backgroundColor: '#007bff',
    paddingHorizontal: 20,
    marginLeft: 10,
    borderRadius: 8,
    justifyContent: 'center',
  },
  addButtonText: {
    color: 'white',
    fontWeight: 'bold',
    fontSize: 16,
  },
  todoList: {
    flex: 1,
  },
  todoItem: {
    flexDirection: 'row',
    backgroundColor: 'white',
    padding: 15,
    marginVertical: 5,
    borderRadius: 8,
    alignItems: 'center',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
    elevation: 2,
  },
  todoText: {
    flex: 1,
  },
  todoTextContent: {
    fontSize: 16,
    color: '#333',
  },
  completedText: {
    textDecorationLine: 'line-through',
    color: '#888',
  },
  deleteButton: {
    backgroundColor: '#dc3545',
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 4,
  },
  deleteButtonText: {
    color: 'white',
    fontSize: 12,
    fontWeight: 'bold',
  },
  summary: {
    textAlign: 'center',
    marginTop: 20,
    fontSize: 16,
    color: '#666',
  },
});

export default TodoApp;

Summary

React Native bridges the gap between web development and mobile app development, allowing React developers to leverage their existing skills to build native mobile applications. Key takeaways from this chapter include:

  1. Component Mapping: Understanding how web components translate to mobile components
  2. Styling Differences: Using StyleSheet instead of CSS
  3. Navigation: Implementing screen-to-screen navigation
  4. Platform-Specific Code: Handling iOS and Android differences
  5. Performance Considerations: Optimizing for mobile devices
  6. Development Tools: Using debugging and development tools effectively

React Native offers a powerful way to build cross-platform mobile applications while maintaining the familiar React development experience. As you continue your React Native journey, focus on understanding platform-specific design patterns and mobile user experience principles.

Next Steps

In the next chapter, we’ll explore deployment strategies for React applications, covering various hosting options and deployment pipelines for both web and mobile applications.

Related Articles

Scroll to Top