React Native App Development
Overview
Create robust cross-platform mobile applications using React Native with modern development patterns including navigation, state management, API integration, and native module handling.
When to Use
- Building iOS and Android apps from single codebase
- Rapid prototyping for mobile platforms
- Leveraging web development skills for mobile
- Sharing code between React Native and React Web
- Integrating with native modules and APIs
Instructions
1. Project Setup & Navigation
// Navigation with React Navigation
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Ionicons } from "@expo/vector-icons";
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function HomeStack() {
return (
<Stack.Navigator
screenOptions={{
headerStyle: { backgroundColor: "#6200ee" },
headerTintColor: "#fff",
headerTitleStyle: { fontWeight: "bold" },
}}
>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: "Home Feed" }}
/>
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
const icons = {
HomeTab: focused ? "home" : "home-outline",
ProfileTab: focused ? "person" : "person-outline",
};
return (
<Ionicons name={icons[route.name]} size={size} color={color} />
);
},
})}
>
<Tab.Screen name="HomeTab" component={HomeStack} />
<Tab.Screen name="ProfileTab" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
2. State Management with Redux
import { createSlice, configureStore } from "@reduxjs/toolkit";
import { useSelector, useDispatch } from "react-redux";
const itemsSlice = createSlice({
name: "items",
initialState: { list: [], loading: false, error: null },
reducers: {
setItems: (state, action) => {
state.list = action.payload;
state.loading = false;
},
setLoading: (state) => {
state.loading = true;
},
setError: (state, action) => {
state.error = action.payload;
state.loading = false;
},
},
});
export const store = configureStore({
reducer: { items: itemsSlice.reducer },
});
export function HomeScreen() {
const dispatch = useDispatch();
const { list, loading, error } = useSelector((state) => state.items);
React.useEffect(() => {
dispatch(setLoading());
fetch("https://api.example.com/items")
.then((r) => r.json())
.then((data) => dispatch(setItems(data)))
.catch((err) => dispatch(setError(err.message)));
}, [dispatch]);
if (loading) return <ActivityIndicator size="large" />;
if (error) return <Text>Error: {error}</Text>;
return (
<ScrollView>
{list.map((item) => (
<ItemCard key={item.id} item={item} />
))}
</ScrollView>
);
}
3. API Integration with Axios
import axios from "axios";
import AsyncStorage from "@react-native-async-storage/async-storage";
const apiClient = axios.create({
baseURL: "https://api.example.com",
timeout: 10000,
});
// Request interceptor for auth
apiClient.interceptors.request.use(
async (config) => {
const token = await AsyncStorage.getItem("authToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error),
);
// Response interceptor for token refresh
apiClient.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
const refreshToken = await AsyncStorage.getItem("refreshToken");
const { data } = await axios.post(
"https://api.example.com/auth/refresh",
{ refreshToken },
);
await AsyncStorage.setItem("authToken", data.accessToken);
apiClient.defaults.headers.Authorization = `Bearer ${data.accessToken}`;
return apiClient(originalRequest);
} catch (refreshError) {
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
},
);
export const fetchUser = () => apiClient.get("/user/profile");
export const fetchItems = (page) => apiClient.get(`/items?page=${page}`);
export const createItem = (data) => apiClient.post("/items", data);
4. Functional Component with Hooks
import React, { useState, useEffect, useCallback } from "react";
import {
View,
Text,
TouchableOpacity,
StyleSheet,
ActivityIndicator,
} from "react-native";
export function DetailsScreen({ route, navigation }) {
const { itemId } = route.params;
const [item, setItem] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
loadItem();
}, [itemId]);
const loadItem = useCallback(async () => {
try {
setLoading(true);
const response = await fetch(`https://api.example.com/items/${itemId}`);
const data = await response.json();
setItem(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}, [itemId]);
if (loading) return <ActivityIndicator size="large" />;
if (error) return <Text>Error: {error}</Text>;
return (
<View style={styles.container}>
<Text style={styles.title}>{item?.title}</Text>
<Text style={styles.description}>{item?.description}</Text>
<TouchableOpacity
style={styles.button}
onPress={() => navigation.goBack()}
>
<Text style={styles.buttonText}>Go Back</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: { padding: 16, flex: 1 },
title: { fontSize: 24, fontWeight: "bold", marginBottom: 8 },
description: { fontSize: 16, color: "#666", marginBottom: 16 },
button: { backgroundColor: "#6200ee", padding: 12, borderRadius: 8 },
buttonText: { color: "#fff", fontWeight: "bold", textAlign: "center" },
});
Best Practices
✅ DO
- Use functional components with React Hooks
- Implement proper error handling and loading states
- Use Redux or Context API for state management
- Leverage React Navigation for routing
- Optimize list rendering with FlatList
- Handle platform-specific code elegantly
- Use TypeScript for type safety
- Test on both iOS and Android
- Use environment variables for API endpoints
- Implement proper memory management
❌ DON'T
- Use inline styles excessively (use StyleSheet)
- Make API calls without error handling
- Store sensitive data in plain text
- Ignore platform differences
- Create large monolithic components
- Use index as key in lists
- Make synchronous operations
- Ignore battery optimization
- Deploy without testing on real devices
- Forget to unsubscribe from listeners