Back to all articles

React Native Development: Complete Guide 2025

React Native powers apps from Facebook, Instagram, Airbnb, and thousands more, with 42% of developers using it for cross-platform development. Write once, deploy to both iOS and Android with near-native performance. This comprehensive guide takes you from setup to production-ready apps.

Why React Native?

Benefits

  • Code reuse: 90%+ code shared between platforms
  • Fast development: Hot reload speeds up iteration
  • Native performance: Native components, not WebView
  • Large ecosystem: npm packages + native modules
  • React knowledge: Use existing React skills
  • Cost effective: One team for both platforms
  • Active community: Massive support and resources

When to Use React Native

✅ Great for:
- Apps with standard UI components
- Cross-platform business apps
- MVPs and prototypes
- Content-heavy apps
- Social media apps
- E-commerce apps
- Chat/messaging apps

⚠️ Consider Native for:
- Heavy graphics (3D games)
- Intensive AR/VR
- Apps needing latest platform features immediately
- Apps with complex native integrations
- Performance-critical apps (though RN is fast)

Companies using React Native:
- Facebook/Meta
- Instagram
- Discord
- Shopify
- Microsoft (Outlook, Xbox)
- Tesla
- Walmart
- Bloomberg

Setup and Installation

Environment Setup

macOS Setup (iOS + Android)

# Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install Node.js
brew install node

# Install Watchman (file watching)
brew install watchman

# iOS Setup
# Install Xcode from App Store
# Install CocoaPods
sudo gem install cocoapods

# Android Setup
# Install Java
brew install --cask zulu@17

# Download Android Studio
# Install Android SDK via Android Studio
# Configure ANDROID_HOME
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/platform-tools

# Verify installation
node --version
npm --version
watchman --version
pod --version

Create New Project

# Using React Native CLI (recommended for native modules)
npx react-native@latest init MyApp
cd MyApp

# Or using Expo (easier, more features)
npx create-expo-app MyApp
cd MyApp

# Project structure
MyApp/
├── android/           # Android native code
├── ios/              # iOS native code
├── src/              # Your code
│   ├── components/   # React components
│   ├── screens/      # Screen components
│   ├── navigation/   # Navigation setup
│   ├── services/     # API, storage, etc.
│   ├── utils/        # Utilities
│   └── types/        # TypeScript types
├── App.tsx           # Root component
├── package.json
└── tsconfig.json

# Run on iOS
npx react-native run-ios
# Or specific device
npx react-native run-ios --simulator="iPhone 15 Pro"

# Run on Android
npx react-native run-android

# Start Metro bundler
npx react-native start

Core Components

Basic Components

import React from 'react';
import {
  View,
  Text,
  Image,
  ScrollView,
  TextInput,
  TouchableOpacity,
  StyleSheet,
} from 'react-native';

// View: Container (like div)

  Hello World


// Text: All text must be in 

  This is body text


// Image: Display images


// Local image


// ScrollView: Scrollable container

  
    {/* Content */}
  


// TextInput: Text input field


// TouchableOpacity: Touchable with opacity feedback

  Press Me


// Styles
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    padding: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 16,
  },
  image: {
    width: 200,
    height: 200,
    borderRadius: 8,
  },
  input: {
    height: 44,
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    paddingHorizontal: 12,
  },
  button: {
    backgroundColor: '#007AFF',
    paddingVertical: 12,
    paddingHorizontal: 24,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

Lists

import { FlatList, SectionList } from 'react-native';

// FlatList: Efficient list rendering
interface Item {
  id: string;
  title: string;
  description: string;
}

const MyList: React.FC<{ data: Item[] }> = ({ data }) => {
  return (
     item.id}
      renderItem={({ item }) => (
        
          {item.title}
          {item.description}
        
      )}
      ItemSeparatorComponent={() => }
      ListEmptyComponent={() => (
        No items
      )}
      onEndReached={loadMore}
      onEndReachedThreshold={0.5}
      refreshing={isRefreshing}
      onRefresh={handleRefresh}
    />
  );
};

// SectionList: List with sections
interface Section {
  title: string;
  data: Item[];
}

const MySectionList: React.FC<{ sections: Section[] }> = ({ sections }) => {
  return (
     item.id}
      renderItem={({ item }) => (
        
          {item.title}
        
      )}
      renderSectionHeader={({ section }) => (
        
          {section.title}
        
      )}
    />
  );
};

Navigation

React Navigation Setup

# Install dependencies
npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context
npm install @react-navigation/native-stack
npm install @react-navigation/bottom-tabs

# iOS: Install pods
cd ios && pod install && cd ..

// App.tsx
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

// Define route params
type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Settings: undefined;
};

const Stack = createNativeStackNavigator();

// Stack Navigator
function RootNavigator() {
  return (
    
      
       ({
          title: `Profile: ${route.params.userId}`,
        })}
      />
      
    
  );
}

// Tab Navigator
type TabParamList = {
  Home: undefined;
  Search: undefined;
  Profile: undefined;
};

const Tab = createBottomTabNavigator();

function TabNavigator() {
  return (
     ({
        tabBarIcon: ({ focused, color, size }) => {
          // Return icon based on route
          return ;
        },
        tabBarActiveTintColor: '#007AFF',
        tabBarInactiveTintColor: 'gray',
      })}
    >
      
      
      
    
  );
}

// Main App
export default function App() {
  return (
    
      
    
  );
}

// Navigation in components
import { useNavigation, useRoute } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';

type HomeScreenNavigationProp = NativeStackNavigationProp<
  RootStackParamList,
  'Home'
>;

const HomeScreen = () => {
  const navigation = useNavigation();

  return (
    
       navigation.navigate('Profile', { userId: '123' })}
      >
        Go to Profile
      

       navigation.goBack()}>
        Go Back
      
    
  );
};

State Management

Context API

// UserContext.tsx
import React, { createContext, useContext, useState, ReactNode } from 'react';

interface User {
  id: string;
  name: string;
  email: string;
}

interface UserContextType {
  user: User | null;
  setUser: (user: User | null) => void;
  isAuthenticated: boolean;
}

const UserContext = createContext(undefined);

export const UserProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [user, setUser] = useState(null);

  const value = {
    user,
    setUser,
    isAuthenticated: user !== null,
  };

  return (
    
      {children}
    
  );
};

export const useUser = () => {
  const context = useContext(UserContext);
  if (!context) {
    throw new Error('useUser must be used within UserProvider');
  }
  return context;
};

// Usage in App.tsx

  
    
  


// Usage in component
const ProfileScreen = () => {
  const { user, isAuthenticated, setUser } = useUser();

  if (!isAuthenticated) {
    return Please log in;
  }

  return (
    
      Welcome, {user?.name}
    
  );
};

Redux Toolkit

# Install
npm install @reduxjs/toolkit react-redux

// store.ts
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';

export const store = configureStore({
  reducer: {
    user: userReducer,
  },
});

export type RootState = ReturnType;
export type AppDispatch = typeof store.dispatch;

// userSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

interface UserState {
  currentUser: User | null;
  isLoading: boolean;
}

const initialState: UserState = {
  currentUser: null,
  isLoading: false,
};

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    setUser: (state, action: PayloadAction) => {
      state.currentUser = action.payload;
    },
    clearUser: (state) => {
      state.currentUser = null;
    },
    setLoading: (state, action: PayloadAction) => {
      state.isLoading = action.payload;
    },
  },
});

export const { setUser, clearUser, setLoading } = userSlice.actions;
export default userSlice.reducer;

// App.tsx
import { Provider } from 'react-redux';
import { store } from './store';

export default function App() {
  return (
    
      
        
      
    
  );
}

// Component usage
import { useSelector, useDispatch } from 'react-redux';
import type { RootState, AppDispatch } from './store';
import { setUser } from './userSlice';

const ProfileScreen = () => {
  const user = useSelector((state: RootState) => state.user.currentUser);
  const dispatch = useDispatch();

  const handleLogin = () => {
    dispatch(setUser({ id: '1', name: 'John', email: '[email protected]' }));
  };

  return (
    
      {user ? (
        Welcome, {user.name}
      ) : (
        
          Login
        
      )}
    
  );
};

API Integration

Fetch API

// api/users.ts
export const fetchUsers = async () => {
  try {
    const response = await fetch('https://api.example.com/users');

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching users:', error);
    throw error;
  }
};

export const createUser = async (user: Partial) => {
  const response = await fetch('https://api.example.com/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`,
    },
    body: JSON.stringify(user),
  });

  return response.json();
};

// Component usage
import { useState, useEffect } from 'react';

const UsersScreen = () => {
  const [users, setUsers] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    loadUsers();
  }, []);

  const loadUsers = async () => {
    try {
      setIsLoading(true);
      const data = await fetchUsers();
      setUsers(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'An error occurred');
    } finally {
      setIsLoading(false);
    }
  };

  if (isLoading) {
    return ;
  }

  if (error) {
    return Error: {error};
  }

  return (
     }
      keyExtractor={item => item.id}
    />
  );
};

Axios

# Install
npm install axios

// api/client.ts
import axios from 'axios';

const client = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
  },
});

// Request interceptor
client.interceptors.request.use(
  (config) => {
    const token = getAuthToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// Response interceptor
client.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      // Handle unauthorized
      logout();
    }
    return Promise.reject(error);
  }
);

export default client;

// api/users.ts
import client from './client';

export const fetchUsers = async () => {
  const response = await client.get('/users');
  return response.data;
};

export const fetchUser = async (id: string) => {
  const response = await client.get(`/users/${id}`);
  return response.data;
};

export const createUser = async (user: Partial) => {
  const response = await client.post('/users', user);
  return response.data;
};

Native Modules

Common Native Libraries

# Camera
npm install react-native-camera
npm install react-native-image-picker

# Storage
npm install @react-native-async-storage/async-storage

# Location
npm install react-native-geolocation-service

# Maps
npm install react-native-maps

# Push Notifications
npm install @react-native-firebase/messaging

# Biometrics
npm install react-native-biometrics

# Share
npm install react-native-share

# WebView
npm install react-native-webview

# After installing, for iOS:
cd ios && pod install && cd ..

AsyncStorage Example

import AsyncStorage from '@react-native-async-storage/async-storage';

// Save data
export const saveData = async (key: string, value: any) => {
  try {
    await AsyncStorage.setItem(key, JSON.stringify(value));
  } catch (error) {
    console.error('Error saving data:', error);
  }
};

// Load data
export const loadData = async (key: string): Promise => {
  try {
    const value = await AsyncStorage.getItem(key);
    return value ? JSON.parse(value) : null;
  } catch (error) {
    console.error('Error loading data:', error);
    return null;
  }
};

// Remove data
export const removeData = async (key: string) => {
  try {
    await AsyncStorage.removeItem(key);
  } catch (error) {
    console.error('Error removing data:', error);
  }
};

// Usage
await saveData('user', { id: '1', name: 'John' });
const user = await loadData('user');
await removeData('user');

Best Practices

Performance

// Use React.memo for expensive components
export const ExpensiveComponent = React.memo(({ data }) => {
  return {/* Render */};
});

// Use useMemo for expensive calculations
const sortedData = useMemo(() => {
  return data.sort((a, b) => a.name.localeCompare(b.name));
}, [data]);

// Use useCallback for event handlers
const handlePress = useCallback(() => {
  console.log('Pressed');
}, []);

// Optimize images


// Use FlatList, not ScrollView for long lists


// Avoid inline styles and functions
// ❌ Bad

   handlePress(item.id)}>
  


// ✅ Good

  
  

Testing

Jest and React Native Testing Library

# Install
npm install --save-dev @testing-library/react-native @testing-library/jest-native

// Button.test.tsx
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import { Button } from './Button';

describe('Button', () => {
  it('renders correctly', () => {
    const { getByText } = render(

Deployment

Build for Production

# iOS
# 1. Open Xcode project
# 2. Select "Any iOS Device" as target
# 3. Product > Archive
# 4. Upload to App Store Connect

# Android
# Generate release keystore
keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

# Build release APK
cd android
./gradlew assembleRelease

# Or AAB (for Play Store)
./gradlew bundleRelease

# Find output:
# APK: android/app/build/outputs/apk/release/app-release.apk
# AAB: android/app/build/outputs/bundle/release/app-release.aab

Conclusion

React Native enables building high-quality mobile apps with JavaScript/TypeScript while maintaining near-native performance. With a rich ecosystem, active community, and strong backing from Meta, it's an excellent choice for cross-platform development. Start building your app today and deploy to millions of users on both platforms!

Every React Native app needs professional support infrastructure. Our support URL generator creates beautiful, mobile-optimized support pages that integrate seamlessly with your app and meet all app store requirements.

Need a Support URL for Your App?

Generate a compliant, professional support page in under a minute. Our easy-to-use generator creates everything you need for App Store and Google Play submissions.