0
0
React Nativemobile~20 mins

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

Choose your learning style9 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.