Access Camera Roll With React Native

Published Jul 10, 2017Last updated Jul 11, 2017
Access Camera Roll With React Native

I started learning React Native 2 months ago and I found out that most of the issues I encountered while trying to implement features such as taking a picture, accessing photos on a phone, chats, authentication were a bit difficult to achieve because the React Native documentation sometimes didn't do justice in explaining these concepts. I had to resort to using libraries to quickly achieve what I set out to achieve.

I've decided to document most of the features I've implemented using the React Native APIs. Here is a simple tutorial using the cameral roll API to access photos in your device. You should check out the React Native documentation.

Setting up React Native

If you haven't built any React Native application, this is a really simple tutorial to get started with. Since I'll be building for the IOS platform, the set up will gear towards that platform.Go to the React Native Site and follow the steps on Building projects with native code.
Screen Shot 2017-07-05 at 4.18.28 PM.png

You can also use the create-react-native-app to have a quick setup.

By now, you should have your app up and running on either the emulator or iPhone device. Here is my folder structure.

In my project folder, I created a component folder that has 3 components namely:

  • CameraScreen.js - add photo button and access to camera roll occurs here.
  • ViewPhotos.js - displays photos from your iPhone.
  • SelectedPhoto.js - shows the selected photo.

Yes I know, my naming is 😀. But you get the whole idea. I removed almost all the boilerplate code in my index.ios.js, you should have something like this:

index.ios.js

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';
import CameraScreen from './component/CameraScreen';

export default class cameraRollExample extends Component {
  render() {
    return (
      <CameraScreen/>
    );
  }
}

AppRegistry.registerComponent('cameraRollExample', () => cameraRollExample);

In my CameraScreen.js, I've made a simple UI that has the add photo button, and I've also imported the CameraRoll module from React Native.
CameraScreen.js

import React, { Component } from 'react';
import {
  CameraRoll,
  Image,
  StyleSheet,
  TouchableHighlight,
  View,
} from 'react-native';

class CameraScreen extends Component {

  render() {
    return (
      <View style={styles.container}>
        <TouchableHighlight>
          <Image
            source={require('../assets/addPhoto.png')} />
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  }
});

export default CameraScreen;

You should have this:
Screen Shot 2017-07-07 at 5.19.15 PM.png

In order to access the photos, you need a click event. Add the onPress prop to your button and call the method getPhotosFromGallery() on it.

//...
render() {
  return (
      <View style={styles.container}>
        <TouchableHighlight
          onPress={() => this.getPhotosFromGallery()}>
          <Image
            source={require('../assets/addPhoto.png')} />
        </TouchableHighlight>
      </View>
    );
}

getPhotosFromGallery()

//...
 getPhotosFromGallery() {
    CameraRoll.getPhotos({ first: 1000000 })
      .then(res => {
        console.log(res, "images data")
      })
  }
  //...

The object inside getPhotos({ first: 1000000}) is used to specify the number of images you want to get from the gallery. When you run the app, you will get this error:
error.png

This error occurs because you haven't added or linked the camera roll library to your Build Phases in Xcode. This is known as manual linking. To do this,

  • go to your project folder
  • open the IOS folder
  • go to the file that has .xcodeproj as the extension, in my case it's cameraRollExample.xcodeproj
  • open this file in your Xcode.

Once it's opened, you should have this.
Screen Shot 2017-07-06 at 9.54.46 AM.png

Next, you need to drag the RCTCameraRoll.xcodeproj in your project folder to Xcode. Here is a simple diagram on where to find this file.
tree.png

Drag the RCTCameraRoll.xcodeproj file to the libraries file in Xcode and then click on Build Phases on the top right-hand corner in Xcode. Click the drop down of Link Binary With Libraries, then the + sign to add the libRCTCameraRoll.a.
Screen Shot 2017-07-06 at 10.17.04 AM.png

Run the build and restart your emulator or device. You should see the image object in you log.
Screen Shot 2017-07-06 at 10.26.54 AM.png

In order to see the images, you need the uri in the image object. Here is an updated version of the CameraRoll.js.

CameraRoll.js

//...
import ViewPhotos from './ViewPhotos';

class CameraScreen extends Component {

  state = {
    showPhotoGallery: false,
    photoArray: []
  }

  getPhotosFromGallery() {
    CameraRoll.getPhotos({ first: 1000000 })
      .then(res => {
        let photoArray = res.edges;
        this.setState({ showPhotoGallery: true, photoArray: photoArray })
      })
  }

  render() {
    if (this.state.showPhotoGallery) {
      return (
        <ViewPhotos
          photoArray={this.state.photoArray} />
      )
    }
    return (
      <View style={styles.container}>

        <TouchableHighlight
          onPress={() => this.getPhotosFromGallery()}>
          <Image
            source={require('../assets/addPhoto.png')} />
        </TouchableHighlight>
      </View>
    );
  }
}
//...

I imported the ViewPhotos.js, in the code snippets above. This is to display the images in a list view.

ViewPhotos.js

import React, { Component } from 'react';
import {
  Image,
  View,
  ListView,
  StyleSheet,
  Text,
  TouchableHighlight

} from 'react-native';

import SelectedPhoto from './SelectedPhoto';

class ViewPhotos extends Component {
  state = {
    ds: new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    }),
    showSelectedPhoto: false,
    uri: ''
  }

  renderRow(rowData) {
    const { uri } = rowData.node.image;
    return (
      <TouchableHighlight
        onPress={() => this.setState({ showSelectedPhoto: true, uri: uri })}>
        <Image
          source={{ uri: rowData.node.image.uri }}
          style={styles.image} />
      </TouchableHighlight>
    )
  }

  render() {
    const { showSelectedPhoto, uri } = this.state;

    if (showSelectedPhoto) {
      return (
        <SelectedPhoto
          uri={uri} />
      )
    }
    return (
      <View style={{ flex: 1 }}>
        <View style={{ alignItems: 'center', marginTop: 15 }}>
          <Text style={{ fontSize: 20, fontWeight: '600' }}>Pick A Photo </Text>
        </View>
        <ListView
          contentContainerStyle={styles.list}
          dataSource={this.state.ds.cloneWithRows(this.props.photoArray)}
          renderRow={(rowData) => this.renderRow(rowData)}
          enableEmptySections={true} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  list: {
    flexDirection: 'row',
    flexWrap: 'wrap'
  },

  image: {
    width: 110,
    height: 120,
    marginLeft: 10,
    marginTop: 10,
    borderRadius: 5,
    borderWidth: 1,
    borderColor: '#979797'
  }
})

export default ViewPhotos;

Here is the screen:
photos.png

When you click or select a photo from the list, you will see the selected photo in the SelectedPhoto.js component.

SelectedPhoto.js

import React from 'react';
import {
  Image,
  View,
  StyleSheet,
  Text,
  TouchableHighlight
} from 'react-native';

const SelectedPhoto = (props) => {
  const { uri } = props;
  return (
    <View style={styles.container}>
      <Image
        source={{uri: uri}}
        style={styles.image}/>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  image: {
    height: 300,
    width: 200
  }
});

export default SelectedPhoto;

selectedPhoto.png

Conclusion

I've run the app on iPhone 6s and iPhone 6s plus. I would love to see builds from other versions and get your feedback and experience. Here is the github repo with the complete app. Gracias 😇

Thanks for reading and feel free to like and share.

Discover and read more posts from blessingoraz
get started
Enjoy this post?

Leave a like and comment for blessingoraz

7
2
2Replies
Ayoola Solomon
2 months ago

Good job

Aliyu Abdullahi
2 months ago

Nice one Blessing.

Get curated posts in your inbox

Read more posts to become a better developer