React Native Reference: Core Components, Styles, Navigation, APIs & Expo
React Native lets you build iOS and Android apps using React. Styles use a subset of CSS via StyleSheet.create() — Flexbox is the default layout system and works like web Flexbox but with a few differences: flexDirection defaults to column (not row), and percentage-based dimensions aren’t supported in all contexts. For new projects, start with Expo — it handles the native build complexity so you can focus on your app. Use bare React Native only if you need maximum native module access.
1. Core Components
View, Text, Image, ScrollView, FlatList, TextInput, TouchableOpacity, and SafeAreaView
import {
View, Text, Image, ScrollView, FlatList,
TextInput, TouchableOpacity, Pressable,
StyleSheet, SafeAreaView, Platform,
} from "react-native";
// View = div, Text = p/span (ALL text must be in Text):
<View style={styles.container}>
<Text style={styles.title}>Hello React Native</Text>
</View>
// Image:
<Image source={require("./assets/logo.png")} style={{ width: 100, height: 100 }} />
<Image source={{ uri: "https://example.com/photo.jpg" }} style={{ width: 200, height: 200 }} />
// FlatList — virtualized list (use instead of .map() for long lists):
<FlatList
data={users}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <UserCard user={item} />}
ListEmptyComponent={<Text>No users found</Text>}
ListHeaderComponent={<Text style={styles.header}>Users</Text>}
onEndReached={loadMore}
onEndReachedThreshold={0.5} // trigger when 50% from bottom
/>
// TouchableOpacity / Pressable for tappable elements:
<TouchableOpacity onPress={() => navigate("Profile")} activeOpacity={0.7}>
<Text>View Profile</Text>
</TouchableOpacity>
// Pressable — more control over press states:
<Pressable
onPress={handlePress}
style={({ pressed }) => [styles.button, pressed && styles.pressed]}
>
{({ pressed }) => <Text>{pressed ? "Pressing..." : "Press me"}</Text>}
</Pressable>
// SafeAreaView — respects notch / status bar:
<SafeAreaView style={{ flex: 1 }}>
<YourApp />
</SafeAreaView>
2. StyleSheet & Flexbox
StyleSheet.create(), Flexbox layout, Platform-specific styles, and dimensions
import { StyleSheet, Platform, Dimensions, useWindowDimensions } from "react-native";
const styles = StyleSheet.create({
container: {
flex: 1, // fill available space
flexDirection: "column", // default (not "row" like web!)
justifyContent: "center", // main axis
alignItems: "center", // cross axis
backgroundColor: "#f8fafc",
padding: 16,
},
row: {
flexDirection: "row",
gap: 12, // RN 0.71+ supports gap
},
card: {
flex: 1, // equal width in row
borderRadius: 8,
padding: 16,
backgroundColor: "#fff",
// Shadow (iOS):
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
// Shadow (Android):
elevation: 4,
},
});
// Platform-specific styles:
const platformStyle = {
...Platform.select({
ios: { fontFamily: "SF Pro Text", paddingTop: 20 },
android: { fontFamily: "Roboto", paddingTop: 24 },
web: { fontFamily: "system-ui", paddingTop: 0 },
}),
};
// Responsive dimensions:
const { width, height } = Dimensions.get("window");
// Or with hook (updates on rotation):
function MyComp() {
const { width } = useWindowDimensions();
return <View style={{ width: width * 0.9 }} />;
}
3. Navigation (React Navigation)
Stack navigator, tab navigator, passing params, and navigation hooks
// npm install @react-navigation/native @react-navigation/native-stack
// npm install react-native-screens react-native-safe-area-context
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
type RootStackParamList = {
Home: undefined;
Profile: { userId: string };
Settings: undefined;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
const Tab = createBottomTabNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen}
options={{ title: "User Profile", headerBackTitle: "Back" }} />
<Stack.Screen name="Settings" component={SettingsScreen}
options={{ presentation: "modal" }} />
</Stack.Navigator>
</NavigationContainer>
);
}
// Navigate + pass params:
navigation.navigate("Profile", { userId: "alice" });
navigation.push("Profile", { userId: "bob" }); // add to stack (even if same screen)
navigation.goBack();
navigation.replace("Home"); // replace current screen
// Access params:
function ProfileScreen({ route, navigation }) {
const { userId } = route.params;
}
// Or with hooks:
import { useNavigation, useRoute } from "@react-navigation/native";
const navigation = useNavigation();
const route = useRoute<RouteProp<RootStackParamList, "Profile">>();
4. APIs — AsyncStorage, Permissions & Platform
AsyncStorage, camera/location permissions, Linking, Vibration, and Expo APIs
// AsyncStorage (npm install @react-native-async-storage/async-storage):
import AsyncStorage from "@react-native-async-storage/async-storage";
await AsyncStorage.setItem("user-token", JSON.stringify(token));
const raw = await AsyncStorage.getItem("user-token");
const token = raw ? JSON.parse(raw) : null;
await AsyncStorage.removeItem("user-token");
await AsyncStorage.clear(); // wipe all storage
// Permissions (Expo: expo-location, expo-camera, expo-notifications):
import * as Location from "expo-location";
import { Camera } from "expo-camera";
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") return; // permission denied
const loc = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High });
const { latitude, longitude } = loc.coords;
const [permission] = await Camera.requestCameraPermissionsAsync();
// Linking — open URLs, deep links:
import { Linking } from "react-native";
await Linking.openURL("https://example.com");
await Linking.openURL("mailto:support@example.com");
await Linking.openURL("tel:+15551234567");
// Vibration:
import { Vibration } from "react-native";
Vibration.vibrate(100); // 100ms vibration
Vibration.vibrate([0, 100, 50, 100]); // pattern: wait, vibrate, wait, vibrate
Vibration.cancel();
// Keyboard:
import { Keyboard, KeyboardAvoidingView } from "react-native";
Keyboard.dismiss();
// Wrap form in KeyboardAvoidingView to avoid keyboard covering input:
<KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"} style={{ flex: 1 }}>
<TextInput ... />
</KeyboardAvoidingView>
5. Expo vs Bare RN, Performance & Testing
Expo workflow, performance tips (memo, FlatList), and testing with Jest + RNTL
// Expo (recommended for most projects):
npx create-expo-app@latest my-app --template default // TypeScript + file-based routing
cd my-app
npx expo start // run on device via Expo Go app, or simulator
// Expo Router — file-based navigation (like Next.js App Router):
// app/index.tsx → /
// app/profile/[id].tsx → /profile/:id
// app/(tabs)/home.tsx → tab route
import { useLocalSearchParams, Link } from "expo-router";
const { id } = useLocalSearchParams();
<Link href="/profile/alice">View Profile</Link>
// Performance:
// 1. Use FlatList not .map() for long lists — virtualized rendering
// 2. memo() for expensive components:
const UserCard = React.memo(({ user }) => <View>...</View>);
// 3. useCallback for callbacks passed to memoized children
// 4. InteractionManager.runAfterInteractions for heavy work after animations
import { InteractionManager } from "react-native";
InteractionManager.runAfterInteractions(() => { heavyWork(); });
// 5. useMemo for expensive calculations
// 6. Avoid anonymous functions in render (creates new ref each render)
// Testing (React Native Testing Library):
// npm install -D @testing-library/react-native
import { render, screen, fireEvent } from "@testing-library/react-native";
it("renders greeting", () => {
render(<Greeting name="Alice" />);
expect(screen.getByText("Hello, Alice")).toBeTruthy();
fireEvent.press(screen.getByText("Say hi"));
expect(screen.getByText("Hi!")).toBeTruthy();
});
Track Node.js and React ecosystem releases at ReleaseRun. Related: React Reference | TypeScript Reference | Zustand Reference
🔍 Free tool: npm Package Health Checker — check react-native and its ecosystem packages for EOL status, known CVEs, and active maintenance.
Founded
2023 in London, UK
Contact
hello@releaserun.com