Author avatar

Chris Parker

Accessing Camera Roll Using React Native

Chris Parker

  • Sep 3, 2020
  • 8 Min read
  • 6,484 Views
  • Sep 3, 2020
  • 8 Min read
  • 6,484 Views
Web Development
React

Introduction

When learning React Native, we find that majority of issues are encountered while trying to implement features such as taking a picture, accessing photos from the mobile device, chats, authentication, etc. These issues are a bit hard to resolve as the React Native documentation does not explain these concepts very well. Thus, we have to use libraries to achieve any of the above functionalities.

In this guide, we will highlight the features implemented using React Native APIs. This guide will help you implement the camera roll API for accessing pictures on a device. Feel free to also check out the official React Native documentation.

Setting up React Native

For someone just starting to build React Native apps, this should be a fairly simple guide to get started with. We'll be building our app for IOS, so the setup is according to that platform. We can go to the React Native site and follow the steps to build projects with native code.

Also for a quick setup, we can use the create-react-native-app.

By now, the app should be up and running on either the emulator or iPhone device. Below is how the folder structure should look. We have a component folder with three components as below:

  1. CamScreen.js - The add picture button and accessing the camera roll take place here.

  2. ViewPictures.js - Displays pictures from your iPhone.

  3. SelectedPicture.js - Displays the selected picture.

We have the boilerplate code in our index.ios.js. It should look something like this:

index.ios.js

1import React, { Component } from 'react';
2import {
3  AppRegistry,
4  StyleSheet,
5  Text,
6  View
7} from 'react-native';
8import CamScreen from './component/CamScreen';
9
10export default class camRollExample extends Component {
11  render() {
12    return (
13      <CamScreen/>
14    );
15  }
16}
17
18AppRegistry.registerComponent('camRollExample', () => camRollExample);
javascript

In CamScreen.js, we have a simple interface where we have the add picture button, and we also import the CameraRoll module from React Native.

CamScreen.js

1import React, { Component } from 'react';
2import {
3  CameraRoll,
4  Image,
5  StyleSheet,
6  TouchableHighlight,
7  View,
8} from 'react-native';
9
10class CamScreen extends Component {
11
12  render() {
13    return (
14      <View style={styles.container}>
15        <TouchableHighlight>
16          <Image
17            source={require('../assets/addPicture.png')} />
18        </TouchableHighlight>
19      </View>
20    );
21  }
22}
23
24const styles = StyleSheet.create({
25  container: {
26    flex: 1,
27    justifyContent: 'center',
28    alignItems: 'center'
29  }
30});
31
32export default CamScreen;
javascript

Accessing Photos

For accessing photos, we need a click event. Let's add the onPress prop to the button and a handler method called getPicturesFromGallery().

1//...
2render() {
3  return (
4      <View style={styles.container}>
5        <TouchableHighlight
6          onPress={() => this.getPicturesFromGallery()}>
7          <Image
8            source={require('../assets/addPicture.png')} />
9        </TouchableHighlight>
10      </View>
11    );
12}
javascript

getPicturesFromGallery()

1//...
2 getPicturesFromGallery() {
3    CameraRoll.getPhotos({ first: 5000 })
4      .then(res => {
5        console.log(res, "images data")
6      })
7  }
8  //...
javascript

The object inside the getPhotos({ first: 5000 }) is used to specify the number of images that we want to get from the gallery. When we run the app, we'll encounter an error:

"Cannot read property 'getPhotos' of undefined"

The above error happens because the camera roll library has not been added or linked to our build phases in Xcode. To fix the error, we'll:

  1. Go to our project directory

  2. Open IOS directory

  3. Navigate to the file that has .xcodeproj as the extension. In our case, it should be camRollExample.xcodeproj

  4. Open this file in Xcode.

Next, we should drag RCTCamRoll.xcodeproj in our project directory to Xcode.

Let's drag the RCTCamRoll.xcodeproj file to libraries file in Xcode. We can then click on Build Phases located in the top right-hand corner in Xcode. Let's click the dropdown next to Link Binary With Libraries, then the + sign to add libRCTCamRoll.a.

We can then run the build and restart our emulator or device. The image object should be visible in our log. To check the images, we need to have the uri in the image object. Here is an updated version of CameraRoll.js.

CameraRoll.js

1//...
2import ViewPictures from './ViewPictures';
3
4class CamScreen extends Component {
5
6  state = {
7    showPhotoGallery: false,
8    pictureArray: []
9  }
10
11  getPicturesFromGallery() {
12    CameraRoll.getPhotos({ first: 5000})
13      .then(res => {
14        let pictureArray = res.edges;
15        this.setState({ showPhotoGallery: true, pictureArray: pictureArray })
16      })
17  }
18
19  render() {
20    if (this.state.showPhotoGallery) {
21      return (
22        <ViewPictures
23          pictureArray={this.state.pictureArray} />
24      )
25    }
26    return (
27      <View style={styles.container}>
28
29        <TouchableHighlight
30          onPress={() => this.getPicturesFromGallery()}>
31          <Image
32            source={require('../assets/addPicture.png')} />
33        </TouchableHighlight>
34      </View>
35    );
36  }
37}
38//...
javascript

In the above code snippets, we just imported ViewPictures.js. This is for displaying the images inside of a list view.

ViewPictures.js

1import React, { Component } from 'react';
2import {
3  Image,
4  View,
5  ListView,
6  StyleSheet,
7  Text,
8  TouchableHighlight
9
10} from 'react-native';
11
12import SelectedPicture from './SelectedPicture';
13
14class ViewPictures extends Component {
15  state = {
16    ds: new ListView.DataSource({
17      rowHasChanged: (r1, r2) => r1 !== r2
18    }),
19    showSelectedPicture: false,
20    uri: ''
21  }
22
23  renderRow(rowData) {
24    const { uri } = rowData.node.image;
25    return (
26      <TouchableHighlight
27        onPress={() => this.setState({ showSelectedPicture: true, uri: uri })}>
28        <Image
29          source={{ uri: rowData.node.image.uri }}
30          style={styles.image} />
31      </TouchableHighlight>
32    )
33  }
34
35  render() {
36    const { showSelectedPicture, uri } = this.state;
37
38    if (showSelectedPicture) {
39      return (
40        <SelectedPicture
41          uri={uri} />
42      )
43    }
44    return (
45      <View style={{ flex: 1 }}>
46        <View style={{ alignItems: 'center', marginTop: 15 }}>
47          <Text style={{ fontSize: 30, fontWeight: '700' }}>Pick A Picture !</Text>
48        </View>
49        <ListView
50          contentContainerStyle={styles.list}
51          dataSource={this.state.ds.cloneWithRows(this.props.pictureArray)}
52          renderRow={(rowData) => this.renderRow(rowData)}
53          enableEmptySections={true} />
54      </View>
55    );
56  }
57}
58
59const styles = StyleSheet.create({
60  list: {
61    flexDirection: 'row',
62    flexWrap: 'wrap'
63  },
64
65  image: {
66    width: 120,
67    height: 130,
68    marginLeft: 15,
69    marginTop: 15,
70    borderRadius: 6,
71    borderWidth: 2,
72    borderColor: '#efefef'
73  }
74})
75
76export default ViewPictures;
javascript

When we click or select a picture from the list, the selected picture will get displayed in the SelectedPicture.js component.

SelectedPicture.js

1import React from 'react';
2import {
3  Image,
4  View,
5  StyleSheet,
6  Text,
7  TouchableHighlight
8} from 'react-native';
9
10const SelectedPicture = (props) => {
11  const { uri } = props;
12  return (
13    <View style={styles.container}>
14      <Image
15        source={{uri: uri}}
16        style={styles.image}/>
17    </View>
18  );
19};
20
21const styles = StyleSheet.create({
22  container: {
23    flex: 1,
24    justifyContent: 'center',
25    alignItems: 'center'
26  },
27  image: {
28    height: 300,
29    width: 200
30  }
31});
32
33export default SelectedPicture;
javascript

Conclusion

Having run the app on both iPhone 6s and iPhone 6s plus, we can extend the test to other devices and verify how it performs on other platforms.