Capturing Photos and Videos with the Camera in React Native

Camera features power profile photos, social posts, chat attachments, video feeds, marketplace listings, delivery proof photos, and dating profiles. The modern React Native implementation needs camera permissions, microphone permissions for video, safe previews, media validation, and an upload pipeline.
Quick Answerโ
Use expo-camera for camera capture in apps that already use Expo modules.
Use expo-image-picker when the user only needs to select or capture media
through the system picker. For video playback, prefer expo-video; the old
Video component from expo-av is deprecated.
Useful Instamobile docs:
Install Camera Dependenciesโ
npx expo install expo-camera expo-video
If you are adding Expo modules to an existing React Native app, make sure the project has Expo modules configured before installing Expo SDK packages.
For iOS, add clear permission strings to Info.plist or your app config:
NSCameraUsageDescriptionNSMicrophoneUsageDescriptionNSPhotoLibraryUsageDescriptionif the app also reads from the library.
Mega Bundle Sale is ON! Get ALL of our React Native codebases at 90% OFF discount ๐ฅ
Get the Mega BundleBasic Camera Screenโ
Current expo-camera uses CameraView and permission hooks:
import React, { useRef, useState } from 'react';
import { Button, View } from 'react-native';
import {
CameraType,
CameraView,
useCameraPermissions,
useMicrophonePermissions,
} from 'expo-camera';
export function CameraScreen() {
const cameraRef = useRef<CameraView>(null);
const [cameraPermission, requestCameraPermission] = useCameraPermissions();
const [microphonePermission, requestMicrophonePermission] =
useMicrophonePermissions();
const [facing, setFacing] = useState<CameraType>('back');
const [mediaUri, setMediaUri] = useState<string | null>(null);
if (!cameraPermission?.granted) {
return (
<Button title="Allow camera" onPress={requestCameraPermission} />
);
}
async function takePhoto() {
const photo = await cameraRef.current?.takePictureAsync({
quality: 0.8,
skipProcessing: false,
});
if (photo?.uri) {
setMediaUri(photo.uri);
}
}
async function recordVideo() {
if (!microphonePermission?.granted) {
await requestMicrophonePermission();
}
const video = await cameraRef.current?.recordAsync({
maxDuration: 30,
});
if (video?.uri) {
setMediaUri(video.uri);
}
}
return (
<View style={{ flex: 1 }}>
<CameraView ref={cameraRef} style={{ flex: 1 }} facing={facing} />
<Button title="Take photo" onPress={takePhoto} />
<Button title="Record video" onPress={recordVideo} />
<Button
title="Flip"
onPress={() => setFacing(current => (current === 'back' ? 'front' : 'back'))}
/>
</View>
);
}
Keep production UI more defensive than a tutorial snippet: disable buttons while
capture is active, handle onMountError, and show a preview before uploading.
Preview Video with expo-videoโ
Use expo-video for playback:
import { useVideoPlayer, VideoView } from 'expo-video';
export function VideoPreview({ uri }: { uri: string }) {
const player = useVideoPlayer(uri, player => {
player.loop = true;
player.play();
});
return <VideoView player={player} style={{ width: '100%', height: 300 }} />;
}
Upload-Ready Media Checklistโ
Before uploading media:
- check file type;
- check file size;
- limit video duration;
- generate a thumbnail for feeds;
- compress or resize when needed;
- store width, height, duration, and owner ID;
- upload under user-scoped Firebase Storage paths;
- clean up abandoned uploads.
FAQโ
Should I use expo-camera or expo-image-picker?โ
Use expo-camera for custom camera UI. Use expo-image-picker for simpler
library selection or system capture flows.
Can I still use expo-av for video?โ
The old Video component from expo-av is deprecated. Prefer expo-video for
new video playback work.
Why does video capture need microphone permission?โ
Most video capture records audio by default, so iOS and Android can require microphone permission even if your UI focuses on video.
Useful Referencesโ
Looking for a custom mobile application?
Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.
Get in TouchConclusionโ
Camera features are more than takePictureAsync. Production apps need clear
permissions, capture state, previews, media validation, upload progress, and
Storage rules. Build the capture flow together with the upload flow, not as a
separate demo screen.