React-Native FileManager with Firebase Storage
Published: 2021-05-04 18:34:57

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9aio981gusrlzz3126z.png)


#Introduction

This is a simple example how to implement a file manager with React-Native, Firebase & Typescript for iOS & Android.



###What I will cover in this post:
* Fetch & display files from the firebase storage
* Open a file picker and upload the file to firebase
* View & download the files on iOS & Android
* Delete files from the firebase storage



###Attention
1. To keep it simple, I did not add any styles and only used the file names as unique identifiers.
2. Please don't do this in a production app. Use GUIDs instead.
3. You should split the code into different files. This example has some inline functions, that should be placed somewhere else.



#Implementation

This component uses the following npm packages:
* react-native-firebase
* react-native-document-picker
* react-native-image-picker
* react-native-fs

(You need to follow the README setups of these npm packages in advance)


```typescript
import React, { useEffect, useState } from "react";
import storage, { FirebaseStorageTypes } from "@react-native-firebase/storage";
import AntDesignIcon from "react-native-vector-icons/AntDesign";
import { Text, View, TouchableOpacity, Alert, Platform, ActionSheetIOS } from "react-native";
import RNFS from "react-native-fs";
import FileViewer from "react-native-file-viewer";
import { launchImageLibrary } from "react-native-image-picker";
import DocumentPicker from "react-native-document-picker";

const pickDocument = async () => {
  const res = await DocumentPicker.pick({
    type: [DocumentPicker.types.allFiles],
  });

  return { path: res.fileCopyUri, name: res.name };
};

const pickAttachmenet = async () => {
  if (Platform.OS === "ios") {
    const options = ["Image", "Document", "Cancel"];
    ActionSheetIOS.showActionSheetWithOptions(
      { options, cancelButtonIndex: 2, title: "Pick a data type" },
      async (buttonIndex) => {
        if (buttonIndex === 0) {
          // Open Image Picker
          launchImageLibrary({ mediaType: "photo" }, (res) => {
            if (!res.didCancel) {
              return { path: res.uri, name: res.fileName };
            }
          });
        } else if (buttonIndex === 1) {
          // Open Document Picker
          return pickDocument();
        } else {
          // exit
        }
      }
    );
  } else {
    // For Android we can just use the normal DocumentPicker, as it can also access images
    return pickDocument();
  }
};

export const FileManager = () => {
  const [uploads, setUploads] = useState<FirebaseStorageTypes.Reference[]>([]);

  useEffect(() => {
    (async () => {
      const listRef = storage().ref().child("uploads");
      const res = (await listRef.listAll()).items;
      setUploads(res);
    })();
  }, []);

  return (
    <View>
      {uploads.map((upload) => {
        return (
          <View key={upload.name}>
            <TouchableOpacity
              onPress={async () => {
                const localPath = `${RNFS.DocumentDirectoryPath}/${upload.name}`;

                await RNFS.downloadFile({
                  fromUrl: await upload.getDownloadURL(),
                  toFile: localPath,
                }).promise;

                FileViewer.open(localPath, {
                  displayName: upload.name,
                });
              }}
            >
              <Text>{upload.name}</Text>
            </TouchableOpacity>
            <AntDesignIcon
              name="delete"
              onPress={() => {
                Alert.alert(`delete ${upload.name}?`, undefined, [
                  { text: "No" },
                  {
                    text: "Yes",
                    onPress: async () => {
                      const fileRef = storage().ref().child("uploads").child(upload.name);
                      await fileRef.delete();
                      setUploads(uploads.filter((u) => u.name === upload.name));
                    },
                  },
                ]);
              }}
            />
          </View>
        );
      })}

      <TouchableOpacity
        children={<Text>Upload File</Text>}
        onPress={async () => {
          const attachmentInfo = await pickAttachmenet();
          if (attachmentInfo?.name) {
            const fileRef = storage().ref().child("uploads").child(attachmentInfo.name); // Alternatively use custom guids as file names
            const res = await fileRef.putFile(attachmentInfo.path);

            setUploads([...uploads, res.ref]);
          }
        }}
      />
    </View>
  );
};


```