ExpoCameraexpo-cameraReact Native

How to Use the Camera in Expo (expo-camera Tutorial)

Build a camera screen in Expo with expo-camera — request permissions, show a live preview with CameraView, take a photo, flip cameras, and scan barcodes. Minimal SDK 54+ examples.

DeveloperMill2 min read

Whether you're building a QR scanner, a document uploader, or a social app, the camera is a core feature — and expo-camera is the most-searched way to add it. The modern API is refreshingly small: one CameraView component and one useCameraPermissions hook. This tutorial covers preview, capture, flipping, and barcode scanning.

Install

npx expo install expo-camera

Add the config plugin in app.json so the OS shows a permission prompt with your copy:

{
  "expo": {
    "plugins": [
      ["expo-camera", { "cameraPermission": "Allow $(PRODUCT_NAME) to use the camera." }]
    ]
  }
}

Request permission and show a preview

The useCameraPermissions hook returns the current status and a request function:

import { CameraView, useCameraPermissions } from "expo-camera"
import { Button, View } from "react-native"

export default function CameraScreen() {
  const [permission, requestPermission] = useCameraPermissions()

  if (!permission) return <View /> // still loading

  if (!permission.granted) {
    return <Button title="Grant camera access" onPress={requestPermission} />
  }

  return <CameraView style={{ flex: 1 }} facing="back" />
}

Take a photo

Attach a ref and call takePictureAsync():

import { CameraView } from "expo-camera"
import { useRef } from "react"
import { Button, View } from "react-native"

export default function Capture() {
  const cameraRef = useRef<CameraView>(null)

  async function snap() {
    const photo = await cameraRef.current?.takePictureAsync()
    console.log(photo?.uri) // file://... — display or upload this
  }

  return (
    <View style={{ flex: 1 }}>
      <CameraView ref={cameraRef} style={{ flex: 1 }} facing="back" />
      <Button title="Take photo" onPress={snap} />
    </View>
  )
}

Flip between front and back cameras

facing is just a prop — toggle it in state:

import { useState } from "react"

const [facing, setFacing] = useState<"front" | "back">("back")

// <CameraView facing={facing} ... />
// <Button title="Flip" onPress={() => setFacing((f) => (f === "back" ? "front" : "back"))} />

Scan QR codes and barcodes

CameraView scans barcodes natively — no extra library:

<CameraView
  style={{ flex: 1 }}
  barcodeScannerSettings={{ barcodeTypes: ["qr", "ean13"] }}
  onBarcodeScanned={({ data }) => {
    console.log("Scanned:", data)
  }}
/>

Debounce the handler in real apps, since it fires continuously while a code is in view.

Gotchas

  • Call takePictureAsync() only after permission is granted and the view has mounted.
  • On a physical device the preview is sharp; simulators show a placeholder.
  • To save photos to the gallery, pair this with expo-media-library; to upload, send photo.uri with FormData.

Next steps

Need to let users pick an existing photo instead? See how to pick images in Expo with expo-image-picker. To display captured images efficiently, use expo-image. Full list: the top 10 Expo SDK modules.

Frequently asked questions

How do I take a photo with expo-camera?

Attach a ref to the `<CameraView>` component and call `ref.current.takePictureAsync()`. It resolves with an object containing the photo's local `uri`, which you can display, upload, or save.

Does expo-camera work in Expo Go?

Basic camera preview and photo capture work in Expo Go. Some advanced native configuration requires a development build, but for most tutorials Expo Go is enough to get started.

How do I scan QR codes or barcodes with expo-camera?

Pass `barcodeScannerSettings={{ barcodeTypes: ['qr'] }}` and an `onBarcodeScanned` handler to `<CameraView>`. The handler receives the decoded `data` string. No separate barcode library is needed.

Build it faster with a template

Production-ready Expo React Native templates with the patterns from this post already wired up.

Browse templates