Search
  • Kyle

Getting started with Camera in React Native


Updated: Jul 22



Ever wondered how to capture images and videos in react native? In this tutorial, We will be implementing the basic features of the Camera component from expo-camera. Also we will use the Video component from expo-av to play the captured video.

First we need to install our dependencies.

Run command:

 expo install expo-camera expo-av

After doing that, you can as well just paste the code below in the App.js file and see your camera come alive.

import React, { useState, useRef, useEffect } from "react";
import {
 View,
 Text,
 TouchableOpacity,
 SafeAreaView,
 StyleSheet,
 Dimensions,
} from "react-native";
import { Camera } from "expo-camera";
import { Video } from "expo-av";

export default function CameraScreen() {
 const [hasPermission, setHasPermission] = useState(null);
 const [cameraType, setCameraType] = useState(Camera.Constants.Type.back);
 const [isPreview, setIsPreview] = useState(false);
 const [isCameraReady, setIsCameraReady] = useState(false);
 const [isVideoRecording, setIsVideoRecording] = useState(false);
 const [videoSource, setVideoSource] = useState(null);

 const cameraRef = useRef();

 useEffect(() => {
    (async () => {
 const { status } = await Camera.requestPermissionsAsync();
 setHasPermission(status === "granted");
    })();
  }, []);

 const onCameraReady = () => {
 setIsCameraReady(true);
  };

 const takePicture = async () => {
 if (cameraRef.current) {
 const options = { quality: 0.5, base64: true, skipProcessing: true };
 const data = await cameraRef.current.takePictureAsync(options);
 const source = data.uri;
 if (source) {
 await cameraRef.current.pausePreview();
 setIsPreview(true);
 console.log("picture", source);
      }
    }
  };

 const recordVideo = async () => {
 if (cameraRef.current) {
 try {
 const videoRecordPromise = cameraRef.current.recordAsync();

 if (videoRecordPromise) {
 setIsVideoRecording(true);
 const data = await videoRecordPromise;
 const source = data.uri;
 if (source) {
 setIsPreview(true);
 console.log("video source", source);
 setVideoSource(source);
          }
        }
      } catch (error) {
 console.warn(error);
      }
    }
  };

 const stopVideoRecording = () => {
 if (cameraRef.current) {
 setIsPreview(false);
 setIsVideoRecording(false);
 cameraRef.current.stopRecording();
    }
  };

 const switchCamera = () => {
 if (isPreview) {
 return;
    }
 setCameraType((prevCameraType) =>
 prevCameraType === Camera.Constants.Type.back
        ? Camera.Constants.Type.front
        : Camera.Constants.Type.back
    );
  };

 const cancelPreview = async () => {
 await cameraRef.current.resumePreview();
 setIsPreview(false);
 setVideoSource(null);
  };

 const renderCancelPreviewButton = () => (
 <TouchableOpacity onPress={cancelPreview} style={styles.closeButton}>
 <View style={[styles.closeCross, { transform: [{ rotate: "45deg" }] }]} />
 <View
 style={[styles.closeCross, { transform: [{ rotate: "-45deg" }] }]}
 />
 </TouchableOpacity>
  );

 const renderVideoPlayer = () => (
 <Video
 source={{ uri: videoSource }}
 shouldPlay={true}
 style={styles.media}
 />
  );

 const renderVideoRecordIndicator = () => (
 <View style={styles.recordIndicatorContainer}>
 <View style={styles.recordDot} />
 <Text style={styles.recordTitle}>{"Recording..."}</Text>
 </View>
  );

 const renderCaptureControl = () => (
 <View style={styles.control}>
 <TouchableOpacity disabled={!isCameraReady} onPress={switchCamera}>
 <Text style={styles.text}>{"Flip"}</Text>
 </TouchableOpacity>
 <TouchableOpacity
 activeOpacity={0.7}
 disabled={!isCameraReady}
 onLongPress={recordVideo}
 onPressOut={stopVideoRecording}
 onPress={takePicture}
 style={styles.capture}
 />
 </View>
  );

 if (hasPermission === null) {
 return <View />;
  }

 if (hasPermission === false) {
 return <Text style={styles.text}>No access to camera</Text>;
  }

 return (
 <SafeAreaView style={styles.container}>
 <Camera
 ref={cameraRef}
 style={styles.container}
 type={cameraType}
 flashMode={Camera.Constants.FlashMode.on}
 onCameraReady={onCameraReady}
 onMountError={(error) => {
 console.log("camera error", error);
        }}
 />
 <View style={styles.container}>
 {isVideoRecording && renderVideoRecordIndicator()}
 {videoSource && renderVideoPlayer()}
 {isPreview && renderCancelPreviewButton()}
 {!videoSource && !isPreview && renderCaptureControl()}
 </View>
 </SafeAreaView>
  );
}

const WINDOW_HEIGHT = Dimensions.get("window").height;

const closeButtonSize = Math.floor(WINDOW_HEIGHT * 0.032);
const captureSize = Math.floor(WINDOW_HEIGHT * 0.09);

const styles = StyleSheet.create({
 container: {
    ...StyleSheet.absoluteFillObject,
  },
 closeButton: {
 position: "absolute",
 top: 35,
 left: 15,
 height: closeButtonSize,
 width: closeButtonSize,
 borderRadius: Math.floor(closeButtonSize / 2),
 justifyContent: "center",
 alignItems: "center",
 backgroundColor: "#c4c5c4"