Bird
Raised Fist0
React Nativemobile~20 mins

Camera access (expo-camera) in React Native - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Camera Screen
This screen lets the user take a photo using the device camera. It asks for camera permission first. The user can see the camera preview and a button to snap a picture. After taking a photo, the picture is shown on the screen.
Target UI
┌─────────────────────────────┐
│ Camera Screen               │
├─────────────────────────────┤
│ [Camera preview area]       │
│                             │
│                             │
│                             │
│                             │
│                             │
│                             │
│                             │
│                             │
│           [Snap Button]      │
└─────────────────────────────┘
Request camera permission on screen load
Show camera preview if permission granted
Show a button labeled 'Snap' below the preview
When 'Snap' is pressed, take a photo
Display the taken photo below the button
If permission denied, show a message 'No access to camera'
Starter Code
React Native
import React, { useState, useEffect, useRef } from 'react';
import { View, Text, Button, Image, StyleSheet } from 'react-native';
import { Camera } from 'expo-camera';

export default function CameraScreen() {
  const [hasPermission, setHasPermission] = useState(null);
  const [photoUri, setPhotoUri] = useState(null);
  const cameraRef = useRef(null);

  useEffect(() => {
    (async () => {
      // TODO: Request camera permission here
    })();
  }, []);

  const takePicture = async () => {
    // TODO: Take picture and save uri
  };

  return (
    <View style={styles.container}>
      {/* TODO: Show camera preview or permission message here */}
      {/* TODO: Snap button here */}
      {/* TODO: Show taken photo here */}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  camera: { width: 300, height: 400 },
  photo: { width: 300, height: 400, marginTop: 10 }
});
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Solution
React Native
import React, { useState, useEffect, useRef } from 'react';
import { View, Text, Button, Image, StyleSheet } from 'react-native';
import { Camera } from 'expo-camera';

export default function CameraScreen() {
  const [hasPermission, setHasPermission] = useState(null);
  const [photoUri, setPhotoUri] = useState(null);
  const cameraRef = useRef(null);

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

  const takePicture = async () => {
    if (cameraRef.current) {
      const photo = await cameraRef.current.takePictureAsync();
      setPhotoUri(photo.uri);
    }
  };

  if (hasPermission === null) {
    return <View style={styles.container}><Text>Requesting camera permission...</Text></View>;
  }

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

  return (
    <View style={styles.container}>
      <Camera style={styles.camera} ref={cameraRef} />
      <Button title="Snap" onPress={takePicture} />
      {photoUri && <Image source={{ uri: photoUri }} style={styles.photo} />}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  camera: { width: 300, height: 400 },
  photo: { width: 300, height: 400, marginTop: 10 }
});

This solution first asks the user for camera permission when the screen loads using Camera.requestCameraPermissionsAsync(). The permission status is saved in state.

If permission is granted, the camera preview is shown using the Camera component from expo-camera. We keep a reference to the camera with useRef so we can call takePictureAsync() when the user presses the 'Snap' button.

When the button is pressed, the app takes a photo and saves its URI in state. Then the photo is displayed below the button using an Image component.

If permission is denied, a simple message 'No access to camera' is shown instead.

This approach keeps the UI simple and clear, and handles permission states properly.

Final Result
Completed Screen
┌─────────────────────────────┐
│ Camera Screen               │
├─────────────────────────────┤
│ [Camera preview area]       │
│                             │
│                             │
│                             │
│                             │
│                             │
│                             │
│                             │
│                             │
│           [Snap Button]      │
│                             │
│ [Photo preview after snap]  │
└─────────────────────────────┘
When the screen loads, it asks for camera permission.
If permission granted, camera preview appears.
User taps 'Snap' button to take a photo.
The taken photo appears below the button.
If permission denied, a message 'No access to camera' is shown.
Stretch Goal
Add a button to switch between front and back cameras.
💡 Hint
Use Camera's 'type' prop with Camera.Constants.Type.front and back, and toggle it on button press.

Practice

(1/5)
1. What is the first step to use the camera in a React Native app with expo-camera?
easy
A. Directly show the camera preview
B. Request permission to access the camera
C. Take a picture immediately
D. Install a photo editing library

Solution

  1. Step 1: Understand permission requirement

    Mobile apps must ask user permission before accessing hardware like the camera.
  2. Step 2: Request camera permission first

    Using expo-camera, you call permission request functions before showing the camera.
  3. Final Answer:

    Request permission to access the camera -> Option B
  4. Quick Check:

    Permission request = A [OK]
Hint: Always ask permission before using hardware [OK]
Common Mistakes:
  • Trying to show camera preview without permission
  • Taking picture before permission granted
  • Skipping permission request step
2. Which of the following is the correct way to import the Camera component from expo-camera?
easy
A. import Camera from 'expo-camera';
B. import CameraComponent from 'expo-camera';
C. import * as Camera from 'expo-camera';
D. import { Camera } from 'expo-camera';

Solution

  1. Step 1: Check expo-camera export style

    The Camera component is a named export, so it must be imported with curly braces.
  2. Step 2: Use correct import syntax

    Correct syntax is import { Camera } from 'expo-camera'; to access the Camera component.
  3. Final Answer:

    import { Camera } from 'expo-camera'; -> Option D
  4. Quick Check:

    Named import uses curly braces = D [OK]
Hint: Named exports need curly braces in import [OK]
Common Mistakes:
  • Using default import without braces
  • Importing everything as an object
  • Using wrong import names
3. What will be the output of this code snippet inside a React Native component using expo-camera?
const [hasPermission, setHasPermission] = React.useState(null);
React.useEffect(() => {
  (async () => {
    const { status } = await Camera.requestCameraPermissionsAsync();
    setHasPermission(status === 'granted');
  })();
}, []);

return hasPermission === null ? Requesting permission : hasPermission === false ? No access : ;
medium
A. Shows camera preview immediately without permission
B. Shows 'No access' text always
C. Shows 'Requesting permission' text initially, then camera preview if granted
D. Throws a syntax error

Solution

  1. Step 1: Analyze permission state flow

    Initially, hasPermission is null, so it shows 'Requesting permission'.
  2. Step 2: After permission request

    If permission granted, hasPermission becomes true and camera preview shows; if denied, shows 'No access'.
  3. Final Answer:

    Shows 'Requesting permission' text initially, then camera preview if granted -> Option C
  4. Quick Check:

    Permission null -> text, granted -> camera = B [OK]
Hint: Check initial state null shows loading text [OK]
Common Mistakes:
  • Expecting camera preview before permission granted
  • Confusing permission states
  • Ignoring async permission request
4. Identify the error in this React Native code snippet using expo-camera:
const cameraRef = React.useRef(null);

async function takePicture() {
  if (cameraRef) {
    const photo = await cameraRef.current.takePictureAsync();
    console.log(photo.uri);
  }
}
medium
A. cameraRef should be checked as cameraRef.current, not cameraRef
B. takePictureAsync() is not an async function
C. cameraRef must be a state variable, not a ref
D. console.log cannot print photo.uri

Solution

  1. Step 1: Check cameraRef usage

    cameraRef is a ref object; to access the camera instance, use cameraRef.current.
  2. Step 2: Correct condition check

    The condition should check if (cameraRef.current) to ensure the camera is ready.
  3. Final Answer:

    cameraRef should be checked as cameraRef.current, not cameraRef -> Option A
  4. Quick Check:

    Ref object needs .current to access value = C [OK]
Hint: Check .current on refs before use [OK]
Common Mistakes:
  • Checking ref object directly instead of .current
  • Forgetting async on takePictureAsync
  • Misusing console.log for URIs
5. You want to build a React Native app that takes a photo only if the user grants camera permission and then saves the photo URI in state. Which sequence of steps is correct?
hard
A. Request permission -> Show camera preview -> Use ref to take picture -> Save URI in state
B. Show camera preview -> Take picture -> Request permission -> Save URI in state
C. Take picture -> Request permission -> Show camera preview -> Save URI in state
D. Save URI in state -> Request permission -> Show camera preview -> Take picture

Solution

  1. Step 1: Request permission before camera use

    Always ask and confirm permission before showing camera preview.
  2. Step 2: Show camera preview and take picture

    Use a ref to access the camera and take a picture only after permission granted.
  3. Step 3: Save photo URI in state

    Store the photo URI in state to use or display later in the app.
  4. Final Answer:

    Request permission -> Show camera preview -> Use ref to take picture -> Save URI in state -> Option A
  5. Quick Check:

    Permission first, then camera, then save = A [OK]
Hint: Permission first, then camera, then save URI [OK]
Common Mistakes:
  • Taking picture before permission
  • Saving URI before picture taken
  • Showing camera without permission
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard