If you are planning to build a camera app using expo camera SDK, you have came to the right place.
In this article we’re going to explore the React Native Camera Expo in multiple ways.
And I will try my best to make it a full in depth guide with examples, for future references.

Creating a new React native expo project

To get started,
Create a new expo react native project. And if you are confident to try it on your current projects.
It wont differ.

If you took the First option and run the project,
you will be presented by the default React native expo screen below.

React Native Camera Expo Example started code

Next Let’s install the Expo Camera SDK and Expo Permissions using expo Cli

expo install expo-camera
expo install expo-permissions

Now We are ready to Go.

Camera UI Concept

To make our Camera app look a bit interesting, I will try to make it good looking. So I am going to aim for the default Samsung galaxy Camera app, with simple UI. Working in 4 Main components.

To achieve this I am going to split the screen into 2 parts
The Camera View, and The interaction buttons including, a button for taking a picture.
switching from Rear camera to Front camera and vise Versa.
and a button to bring up the camera roll to check the pictures taken.

Let’s Get Started

To access camera in react native you need to import the expo-camera SDK, and Camera permissions from expo-permissions.
Before we can display the camera, or interact with it in any ways.
The app must ask user permission usage for the camera.
Then we can create UI with either the camera show, or a text message asking for the permissions.

the app must ask user permission usage for the camera.
Then we can create UI with either the camera show, or a text message asking for the permissions.

import { Camera } from 'expo-camera';
import * as Permissions from 'expo-permissions';

The best place to ask for user permissions is inside the componentDidMount lifecycle method.
Let’s add that next and save the user permission on state to use it later

In addition to the users’ permission in the state,
lets add a property to hold the camera type to control the type of camera that’s being used (Rear or Front)

  state = {
    hasPermission: null,
    type: Camera.Constants.Type.back,
  }

  async componentDidMount() {
    const { status } = await Permissions.askAsync(Permissions.CAMERA);
    this.setState({ hasPermission: status === 'granted' });
  }

This is the message the user will see, once he lands on the Camera screen.

React Native Camera Expo Example camera permissions

Let’s head the the render method and add the Camera display logic.

  render(){
    const { hasPermission } = this.state
    if (hasPermission === null) {
      return <View />;
    } else if (hasPermission === false) {
      return <Text>No access to camera</Text>;
    } else {
      return (
          <View style={{ flex: 1 }}>
            <Camera style={{ flex: 1 }} type={this.state.cameraType}>
              
            </Camera>
        </View>
      );
    }
  }
  
}

This part simply means, when the camera view will be shown to the user based on his permission.

If the app has the permission,
the Camera will be shown, if not a text message asking for permission, and if the property is null.
it will display an empty view, this usually happens at the start of the app while the componentDidMount is not yet called.

and this is what the app looks like so far like this. and the Camera View Takes the full screen

React Native Camera Expo Example camera component

Add Camera UI

The Camera UI Interaction buttons we will be using, will compose of a TouchableOpacity component, and an Expo Icons component

The app will have 3 buttons each with a different Icon representing an action, and they are.
Taking a photo, Switching between Cameras Types (Rear and Front) and displaying the All the photos taken by this camera.

To Achieve this, let’s add a view inside the Camera components, which will contain the 3 Icon Buttons.

You can explore the entire list of Icons Provided by default by Expo here

To use any Icon, all you need is to match its name and Its Type.
And Add it to the Touchable.

First import the Type of Icons you want to use, as an example Font Awesome

import { FontAwesome } from '@expo/vector-icons';

And use it like this

<FontAwesome name="camera" />

You can add styles to it, and transform it as you like.
you will most likely need to either change its color and its side using these 2 properties


you will most likely need to either change its color and its side using these 2 properties

<FontAwesome
  name="camera"
  style={{ color: "#fff", fontSize: 40}}
/>

Now we are Good to add it all together.

I will be using 3 icons from 3 different types FontAwesome, Ionicons and MaterialCommunityIcons, so let’s start by importing them

import { FontAwesome, Ionicons,MaterialCommunityIcons } from '@expo/vector-icons';

Like we have planned, let’s add a root view inside the camera components to hold the interactions buttons.

<View style={{flex:1, flexDirection:"row",justifyContent:"space-between",margin:20}}>
  <TouchableOpacity
    style={{
      alignSelf: 'flex-end',
      alignItems: 'center',
      backgroundColor: 'transparent',                  
    }}>
    <Ionicons
        name="ios-photos"
        style={{ color: "#fff", fontSize: 40}}
    />
  </TouchableOpacity>
  <TouchableOpacity
    style={{
      alignSelf: 'flex-end',
      alignItems: 'center',
      backgroundColor: 'transparent',
    }}>
    <FontAwesome
        name="camera"
        style={{ color: "#fff", fontSize: 40}}
    />
  </TouchableOpacity>
  <TouchableOpacity
    style={{
      alignSelf: 'flex-end',
      alignItems: 'center',
      backgroundColor: 'transparent',
    }}>
    <MaterialCommunityIcons
        name="camera-switch"
        style={{ color: "#fff", fontSize: 40}}
    />
  </TouchableOpacity>
</View>

I have added a root view style to put it down the screen instead of top.
And added a justifyContent property of value Space Between to split the buttons across the width of the device.

and each buttons has its style to handle the icon inside it.

So fare the app looks like this.

React Native Camera Expo Example Camera UI

Camera UI interactions

Change Expo Camera Type

Switching between camera Type is straight forward.
all you need to do is handle the type prop in the camera component.
And if you remember we have already setup in the state.

And if you remember we have already setup in the state.

and if you remember we have already setup in the state.

So let’s create a function to handle it.


  handleCameraType=()=>{
    const { cameraType } = this.state

    this.setState({cameraType:
      cameraType === Camera.Constants.Type.back
      ? Camera.Constants.Type.front
      : Camera.Constants.Type.back
    })
  }

The function above checks wether the camera View is using the back camera, if so it changes it into the front one.
if not it sets it to the back camera.

No add this function to the onPress props on the touchable and you are set.

<TouchableOpacity
  style={{
    alignSelf: 'flex-end',
    alignItems: 'center',
    backgroundColor: 'transparent',
  }}
  onPress={()=>this.handleCameraType()}
  >
  <MaterialCommunityIcons
      name="camera-switch"
      style={{ color: "#fff", fontSize: 40}}
  />
</TouchableOpacity>

Take Pictures using the Expo Camera

To take a picture, the Expo Camera has a function called takePictureAsync.
And to use to expose a camera component reference, And since this setup is straight forward.
Just add following prop to the camera component and you are set

  ref={ref => {
    this.camera = ref;
  }}

Next, make function to make use the the camera ref and it’s takePictureAsync function.

takePicture = async () => {
  if (this.camera) {
    let photo = await this.camera.takePictureAsync();
  }
}

Now, the photo variable stores information about the taken photo, it’s an object with these proprieties.

URI: The full path to the taken photo file in the device, where its stored
Height: The height of the photo
Width: The width of the photo
base64: if you set the base64 parameter in the takePictureAsync function, it will retrieve JPEG data for the image.
exif: if you set the exif parameter in the takePictureAsync function, it will retrieve EXIF data for the image.

Access Stored Photos using React native CameraRoll

To access the photos we have taken using the camera, we can use the Expo ImagePicker Component,

The expo ImagePicker is a component layer on top of native IOS and Android file picker UI system.
For selecting Images without the need to write code from scratch, it’s pretty handy and easy to use.

Install it first, then import it

expo install expo-image-picker
import * as ImagePicker from 'expo-image-picker';

Again, we will need permissions to access the camera roll of the device, but this time only for IOS devices.
And not for Android.

Let’s make a function for permissions, and include both camera permissions and Camera roll permissions at once.
Then Add to to componentWillMount Method.

async componentDidMount() {
  this.getPermissionAsync()
}  
getPermissionAsync = async () => {
    // Camera roll Permission 
    if (Platform.OS === 'ios') {
      const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
      if (status !== 'granted') {
        alert('Sorry, we need camera roll permissions to make this work!');
      }
    }
    // Camera Permission
    const { status } = await Permissions.askAsync(Permissions.CAMERA);
    this.setState({ hasPermission: status === 'granted' });
  }

All good, once the app is opened, it will ask for both Camera and CameraRoll permissions. And do not forget to import the Platform module from React Native

React Native Camera Expo Example Camera Roll permission

Now, let’s write the a function, to handle the camera roll image list.
And add it to the display photo’s button

  pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
    });
  }

Once the user invokes this function, this screen will display showing the default device’s gallery app.
where they can check their photos.

React Native Camera Expo Example Camera Roll image picker

I have created a github repository for this project, you can access it from here. I will probably improve it a bit later on.
And if you guys request features or UI changes It will be added for sure.
I think that was it for this tutorial.
We have built a fully functioning camera app using React Native Camera Expo There are more options we can explore.
like adding more functionality to the camera, such as zooming, adding focus, and the ability to toggle flash.
You can add more on your project for sure.

Recommended Articles

React Native Flatlist Example

React Native Accessibilityinfo API

React Native Countdown Timer Example Using MomentJs