React Native Cheatsheet

Native APIs

Use this React Native reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Alert

import { Alert } from 'react-native';

// Simple alert
Alert.alert('Title', 'Message');

// With buttons
Alert.alert(
  'Delete Item',
  'Are you sure?',
  [
    { text: 'Cancel', style: 'cancel', onPress: () => {} },
    { text: 'Delete', style: 'destructive', onPress: handleDelete },
  ],
  { cancelable: true }  // Android: dismiss on outside tap
);

// Prompt (iOS only)
Alert.prompt(
  'Enter Name',
  'Type your name below',
  (text) => console.log(text),
  'plain-text',
  'default value'
);

Button style values

'default' | 'cancel' | 'destructive'

Clipboard

npx expo install expo-clipboard
# or: npm install @react-native-clipboard/clipboard
import * as Clipboard from 'expo-clipboard';

// Copy
await Clipboard.setStringAsync('Text to copy');

// Paste
const text = await Clipboard.getStringAsync();

// Check if has string
const has = await Clipboard.hasStringAsync();

// Image (Expo SDK 49+)
await Clipboard.setImageAsync(base64String);
const image = await Clipboard.getImageAsync({ format: 'png' });

Share

import { Share } from 'react-native';

const result = await Share.share({
  message: 'Check this out: https://example.com',
  title: 'Share Title',       // Android title
  url: 'https://example.com', // iOS only; message used on Android
});

if (result.action === Share.sharedAction) {
  console.log('Shared via:', result.activityType);
} else if (result.action === Share.dismissedAction) {
  console.log('Dismissed');
}

Vibration

import { Vibration } from 'react-native';

Vibration.vibrate();              // single buzz
Vibration.vibrate(500);           // 500ms
Vibration.vibrate([0, 500, 200, 500]);  // pattern: wait, vibrate, wait, vibrate
Vibration.vibrate([0, 500], true); // repeat pattern
Vibration.cancel();               // stop repeating

Haptics (Expo)

npx expo install expo-haptics
import * as Haptics from 'expo-haptics';

Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
Haptics.selectionAsync();

Camera

npx expo install expo-camera
import { CameraView, useCameraPermissions, CameraType } from 'expo-camera';
import { useRef, useState } from 'react';

function CameraScreen() {
  const [permission, requestPermission] = useCameraPermissions();
  const cameraRef = useRef<CameraView>(null);
  const [facing, setFacing] = useState<CameraType>('back');

  if (!permission?.granted) {
    return (
      <View>
        <Text>Camera permission required</Text>
        <Pressable onPress={requestPermission}><Text>Grant</Text></Pressable>
      </View>
    );
  }

  const takePicture = async () => {
    const photo = await cameraRef.current?.takePictureAsync({
      quality: 0.8,
      base64: false,
      exif: false,
    });
    console.log(photo?.uri);
  };

  return (
    <CameraView
      ref={cameraRef}
      style={{ flex: 1 }}
      facing={facing}
      flash="auto"    // 'auto' | 'on' | 'off'
    >
      <Pressable onPress={takePicture} style={styles.capture} />
      <Pressable onPress={() => setFacing(f => f === 'back' ? 'front' : 'back')}>
        <Text>Flip</Text>
      </Pressable>
    </CameraView>
  );
}

Image Picker

npx expo install expo-image-picker
import * as ImagePicker from 'expo-image-picker';

// Pick from gallery
const result = await ImagePicker.launchImageLibraryAsync({
  mediaTypes: ['images'],   // 'images' | 'videos' | 'livePhotos' (MediaTypeOptions is deprecated)
  allowsEditing: true,
  aspect: [4, 3],
  quality: 0.8,
  allowsMultipleSelection: true,
  selectionLimit: 5,
});

if (!result.canceled) {
  const { uri, width, height, fileSize, mimeType } = result.assets[0];
  setImageUri(uri);
}

// Take photo with camera
const photo = await ImagePicker.launchCameraAsync({
  mediaTypes: ['images'],
  quality: 1,
});

// Request permissions
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
const { status: cameraStatus } = await ImagePicker.requestCameraPermissionsAsync();

Location

npx expo install expo-location
import * as Location from 'expo-location';

// Request permission
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') return;

// One-time location
const location = await Location.getCurrentPositionAsync({
  accuracy: Location.Accuracy.Balanced,
  // Accuracy: Lowest | Low | Balanced | High | Highest | BestForNavigation
});
const { latitude, longitude, altitude, speed, heading } = location.coords;

// Watch location
const subscription = await Location.watchPositionAsync(
  {
    accuracy: Location.Accuracy.High,
    timeInterval: 5000,    // min ms between updates
    distanceInterval: 10,  // min meters between updates
  },
  (location) => updateMap(location)
);

// Cleanup
subscription.remove();

// Reverse geocode
const [place] = await Location.reverseGeocodeAsync({ latitude, longitude });
console.log(place.city, place.country, place.street);

// Forward geocode
const coords = await Location.geocodeAsync('1600 Amphitheatre Pkwy, Mountain View, CA');

Notifications (Push)

npx expo install expo-notifications
import * as Notifications from 'expo-notifications';

// Configure how notifications are shown
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowBanner: true,   // replaces deprecated shouldShowAlert (SDK 53+)
    shouldShowList: true,     // show in the notification center list
    shouldPlaySound: true,
    shouldSetBadge: false,
  }),
});

// Request permission + get Expo push token
const { status } = await Notifications.requestPermissionsAsync();
const token = (await Notifications.getExpoPushTokenAsync({ projectId: 'your-project-id' })).data;
// Send `token` to your server to store for push notifications

// Schedule local notification
await Notifications.scheduleNotificationAsync({
  content: {
    title: 'Reminder',
    body: 'Time to check in!',
    data: { screen: 'Home' },
    badge: 1,
  },
  trigger: {
    type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL,
    seconds: 60,
    repeats: false,
  },  // triggers require an explicit `type` in current SDKs
});

// Daily notification at specific time
await Notifications.scheduleNotificationAsync({
  content: { title: 'Daily', body: 'Good morning!' },
  trigger: {
    type: Notifications.SchedulableTriggerInputTypes.DAILY,
    hour: 8,
    minute: 0,
  },
});

// Cancel all scheduled
await Notifications.cancelAllScheduledNotificationsAsync();

// Badge
await Notifications.setBadgeCountAsync(5);
await Notifications.setBadgeCountAsync(0);  // clear

// Listeners
const sub1 = Notifications.addNotificationReceivedListener(notification => {
  console.log(notification.request.content);
});

const sub2 = Notifications.addNotificationResponseReceivedListener(response => {
  const data = response.notification.request.content.data;
  navigation.navigate(data.screen);
});

return () => { sub1.remove(); sub2.remove(); };

AppState

import { AppState } from 'react-native';

console.log(AppState.currentState);  // 'active' | 'background' | 'inactive' (iOS)

const sub = AppState.addEventListener('change', nextAppState => {
  if (nextAppState === 'active') {
    // App came to foreground — refresh data, restart timers
  }
  if (nextAppState === 'background') {
    // App went to background — save state, pause timers
  }
});

return () => sub.remove();

Permissions

import { PermissionsAndroid, Platform } from 'react-native';

// Android manual permissions (API < 33)
if (Platform.OS === 'android') {
  const granted = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.CAMERA,
    {
      title: 'Camera Permission',
      message: 'App needs camera access',
      buttonPositive: 'OK',
      buttonNegative: 'Cancel',
    }
  );

  if (granted === PermissionsAndroid.RESULTS.GRANTED) {
    openCamera();
  }
}

// Expo unified API
import { Camera } from 'expo-camera';
const { status } = await Camera.requestCameraPermissionsAsync();
// status: 'granted' | 'denied' | 'undetermined'

Secure Auth Token Pattern (expo-secure-store)

// lib/auth.ts — Keychain (iOS) / Keystore (Android) backed storage
// npx expo install expo-secure-store
import * as SecureStore from 'expo-secure-store';

export const AUTH_KEY = 'auth_token';

export async function saveToken(token: string) {
  await SecureStore.setItemAsync(AUTH_KEY, token);
}

export async function getToken(): Promise<string | null> {
  return SecureStore.getItemAsync(AUTH_KEY);
}

export async function deleteToken() {
  await SecureStore.deleteItemAsync(AUTH_KEY);
}

// In app startup
useEffect(() => {
  getToken().then(token => {
    if (token) dispatch({ type: 'RESTORE_TOKEN', token });
    else dispatch({ type: 'SIGN_OUT' });
  });
}, []);

Sensors (Expo)

npx expo install expo-sensors
import { Accelerometer, Gyroscope, DeviceMotion } from 'expo-sensors';

// Accelerometer
Accelerometer.setUpdateInterval(100);  // ms
const sub = Accelerometer.addListener(({ x, y, z }) => {
  console.log(x, y, z);
});
sub.remove();

// Device orientation
const available = await DeviceMotion.isAvailableAsync();
DeviceMotion.setUpdateInterval(200);
const sub = DeviceMotion.addListener(({ rotation, acceleration }) => {
  const { alpha, beta, gamma } = rotation;  // radians
});