How to upload an image in React Native
Published: 2021-11-29 08:32:09

In this post, we are going to learn how to upload an image in a react native app to Laravel api server.
We are going to use react-native-image-crop-picker, a package to handle upload of an image either using camera or from the gallery.
First, we install this package using npm by using the command below;
```
npm i react-native-image-crop-picker
```
<b>Hooks takePhotoFromCamera() and choosePhotoFromLibrary()</b>
```javascript
import React from 'react';
import ImagePicker from 'react-native-image-crop-picker';

const uploadProfilePicture = () => {

const [isUpdatingImage, setIsUpdatingImage] = useState(false);
const [visible, setVisible] = useState(false);

 const takePhotoFromCamera = () => {
       ImagePicker.openCamera({
        width: 300,
        height: 400,
        cropping: true,
        compressImageQuality: 0.7,
      }).then(image => {
        SubmitProfileUpdateDetails(image);
      });
    }


 const choosePhotoFromLibrary = async() => {
      ImagePicker.openPicker({
        width: 300,
        height: 400,
        cropping: true,
      }).then(async (image) => {
        SubmitProfileUpdateDetails(image);
      });
    }
}

}

```
In the above code snippet, there are two custom hook methods i.e <b>takePhotoFromCamera</b> and <b>choosePhotoFromLibrary</b>.

takePhotoFromCamera() uses openCamera() method on the object imagePicker to allow user upload the photo using camera while choosePhotoFromLibrary() uses openPicker() method on the object imagePicker to allow user upload photo from gallery.

Both hooks call method <b>SubmitProfileUpdateDetails(image)</b> which takes in parameter image (a response object after uploading photo either using camera or from gallery).

<b>Method SubmitProfileUpdateDetails()</b>
```javascript
var mime = require('mime-types') 
// import this at the top of your component

const SubmitProfileUpdateDetails = async(image) => {
      
      const imagePath = image.path;
      const mimeType = image.mime;
      const source = {url: image.path};
      const fileExtension = mime.extension(mimeType);
      setImage(imagePath);

      const ImageData = {
        uri: imagePath,
        type: mimeType,
        size: image.size,
        extension: fileExtension,
        name: 'profile_pic',
      }

      let formData = new FormData();
      formData.append('id', profile.user_id);
      formData.append('phone_number',profile.phone_number);
      formData.append('extension', fileExtension);
      formData.append('image', ImageData);

      setIsUpdatingImage(true);
      let result = await uploadProfilePicture(formData);

      const statusCode = result.statusCode;
      const message = result.message;
      if(statusCode == 1){
        const customer = result.data;
        await setProfile(customer);
        await getProfile(customer);
        Toast.show(message);
      }else{
          Alert.alert("Message", message);
      }
      setIsUpdatingImage(false);
      setVisible(false);
    }


```

The object <b>image</b> has properties; image path and image mime which i use to get image extension.  I form object <b>imageData</b>, containing photo details i.e     image uri, type, size, extension and name. I use FormData interface to append user data (id, phone number, extension and image object) to the formData object.
<b>Note</b>: I use node package <b>mime-types</b> to get file extension of the uploaded photo. The package can be installed using the command <b>npm i mime-types</b>.

The method calls uploadProfilePicture() which takes in formData object containing user details.

<b>Method uploadProfilePicture()</b>
```javascript
const uploadProfilePicture = (data) => {
        const endpoint = "change/profile/image";
        return FileUpload(endpoint, data);
   }

```
Method uploadProfilePicture calls FileUpload which takes in an endpoint <b>"change/profile/image"</b> and user details which are uploaded to the server.
<b>Method FileUpload()</b>
```javascript
const FileUpload = async(endPoint, data) => {
      const url = config.API_URL+""+ endPoint; 
// Replace config.API_URL with your api url
      const response = await fetch(url, {
        method: 'POST',
        body: data,
        headers: {
          Accept: 'application/json',
          'Content-Type': 'multipart/form-data',
          'authToken': 'yourtokenhere',
        },
      });

      var resultSet;
      (response.ok) 
      ? resultSet = await response.json()
      : resultSet = "HTTP-Error: " + response.status;

      return resultSet;
   }

```
FileUpload() uses javascript fetch api to send data to the server using Post method.

<b>Full Code</b>
```javascript

import React from 'react';
import {View, Text,TouchableOpacity} from 'react native';
import FontAwesome from 'react-native-vector-icons/FontAwesome'
import ImagePicker from 'react-native-image-crop-picker';
var mime = require('mime-types')

const uploadProfilePicture = () => {

const [isUpdatingImage, setIsUpdatingImage] = useState(false);
const [visible, setVisible] = useState(false);

 const takePhotoFromCamera = () => {
       ImagePicker.openCamera({
        width: 300,
        height: 400,
        cropping: true,
        compressImageQuality: 0.7,
      }).then(image => {
        SubmitProfileUpdateDetails(image);
      });
    }


 const choosePhotoFromLibrary = async() => {
      ImagePicker.openPicker({
        width: 300,
        height: 400,
        cropping: true,
      }).then(async (image) => {
        SubmitProfileUpdateDetails(image);
      });
    }
}

const SubmitProfileUpdateDetails = async(image) => {
      const imagePath = image.path;
      const mimeType = image.mime;
      const source = {url: image.path};
      const fileExtension = mime.extension(mimeType);
      setImage(imagePath);

      const ImageData = {
        uri: imagePath,
        type: mimeType,
        size: image.size,
        extension: fileExtension,
        name: 'profile_pic',
      }

      let formData = new FormData();
      formData.append('id', profile.user_id);
      formData.append('phone_number',profile.phone_number);
      formData.append('extension', fileExtension);
      formData.append('image', ImageData);

      setIsUpdatingImage(true);
      let result = await uploadProfilePicture(formData);

      const statusCode = result.statusCode;
      const message = result.message;
      if(statusCode == 1){
        const customer = result.data;
        await setProfile(customer);
        await getProfile(customer);
        Toast.show(message);
      }else{
          Alert.alert("Message", message);
      }
      setIsUpdatingImage(false);
      setVisible(false);
    }

const FileUpload = async(endPoint, data) => {
      const url = config.API_URL+""+ endPoint; 
      const response = await fetch(url, {
        method: 'POST',
        body: data,
        headers: {
          Accept: 'application/json',
          'Content-Type': 'multipart/form-data',
          'authToken': 'yourtokenhere',
        },
      });

      var resultSet;
      (response.ok) 
      ? resultSet = await response.json()
      : resultSet = "HTTP-Error: " + response.status;

      return resultSet;
   }

 return(

            <View>
            <View>
            <Text>Upload Profile Photo</Text>
            <Text>Choose Your Profile Picture</Text>
            </View>

            <View>

            <View>
            <TouchableOpacity onPress={()=>{ setVisible(false) }} >
            <FontAwesome name={"trash"} size={25} color= 
    {"#fff"} />
            </TouchableOpacity>
            <Text>Cancel</Text>
            </View>

            <View>
            <TouchableOpacity onPress={choosePhotoFromLibrary} >
            <FontAwesome name={"photo"} size={25}  color={"#fff"}/>
            </TouchableOpacity>
            <Text>Gallery</Text>
            </View>

            <View>
            <TouchableOpacity onPress= 
             {takePhotoFromCamera}> 
            <FontAwesome name={"camera"} size={25} color= 
           {"#fff"}/>
            </TouchableOpacity>
            <Text>Camera</Text>
            </View>

            </View>
            </View>

    );


}
```
<b>Note:</b> Do not forget to install fontawesome package because we use it as well in the example above.
You can use any server technology like laravel to handle the backend.
<b>Laravel code snippet to handle the uploading of the image</b>

```php
  if($request->filled('id') && 
     $request>filled('phone_number') && 
     $request->filled('extension') && 
     $request->has('image')) {
    $file = $request->file('image');
    $user_id = $request->input('id');
    $phone_number = $request->input('phone_number');
    $file_extension = $request->input('extension');

    $doesUserExist = User::where('id', $customer_id)
         ->where('phone_number', $phone_number)->exists();
    if($doesUserExist){
       $user = User::findOrFail($user_id);
       if(!empty($user->image)){
           Storage::disk('public')->delete($user->image);
        }
       $fileName = $user_id.''.time().'.'.$file_extension;
       $filePath = 
               $file->storeAs('images',$fileName,'public');
       $input = ['image' => $filePath];

       if($user->update($input)){
          $message = 'Profile updated successfully';
          $resp->statusCode = '1';
          $resp->message  = $message;
        }else {
          $resp->statusCode = '0';
          $resp->message = "Unable to update profile picture";
       }
 }else{
   $resp->statusCode = '0';
   $resp->message = "Unable to find user";
 }
}
 else{
  $resp->statusCode = '0';
  $resp->message = "Unable to process request";
 }
```
I hope this post gives you a picture of how to upload profile picture or any photo from react native app to the server say laravel. Thank you for taking time to read through this post.