DEV Community

Cover image for How to access file systems with React Native
Megan Lee for LogRocket

Posted on • Originally published at blog.logrocket.com

How to access file systems with React Native

Written by Hussain Arif✏️

Editor’s note: This article was last updated by Hussain Arif on 5 August 2024 to update code blocks so the project is compatible with React Native v0.70 and greater, and to cover sharing file content across apps using the react-native-share library.

Say that you’re working on building an image editor app. In this case, you would let the user perform the following steps: * In the app, access the user’s camera to take photos

  • If the user snaps a photo, import this file to another module that lets them edit the image
  • When the user is done modifying the picture, the app should upload this to social media

Sure, this might work. But there is a minor flaw: what if the client wants to edit an existing image? To make this possible, this means that the program should have access to the user’s file system.

This is where [react-native-fs](https://github.com/itinance/react-native-fs) comes in. It is an easy-to-use library that lets developers read and write files and folders to the host device. In this guide, you will learn the fundamentals of the react-native-fs library and work through some advanced use cases.

This will be the outcome of this article:
Final Outcome With react-native-fs

Here are the steps we’ll take:

Getting started

As a first step, we have to initialize a React Native project using react-native-cli like so:

react-native init fileSystemLearn
Enter fullscreen mode Exit fullscreen mode

When that’s done, install the react-native-fs module:

npm install react-native-fs
react-native link react-native-fs #link this library with our app's native code
Enter fullscreen mode Exit fullscreen mode

Basic usage

Getting file paths RNFS includes a set of constants that informs the user about the list of file paths configured on their device. Some of them include:

  • MainBundleDirectory: The app’s data folder
  • DownloadDirectoryPath: Points toward the user’s Downloads directory
  • ExternalStorageDirectory: Contains the path of the device’s external storage Here’s a brief example of these constants in action:
import {useState, useEffect} from 'react';
import RNFS from 'react-native-fs';
function App() {
  const [downloadsFolder, setDownloadsFolder] = useState('');
  const [documentsFolder, setDocumentsFolder] = useState('');
  const [externalDirectory, setExternalDirectory] = useState('');
  useEffect(() => {
    //get user's file paths from react-native-fs
    setDownloadsFolder(RNFS.DownloadDirectoryPath);
    setDocumentsFolder(RNFS.DocumentDirectoryPath); //alternative to MainBundleDirectory.
    setExternalDirectory(RNFS.ExternalStorageDirectoryPath);
  }, []);
  return (
    <safeareaview><text> Downloads Folder: {downloadsFolder}</text>
      <text>Documents folder: {documentsFolder}</text>
      <text>External storage: {externalDirectory}</text></safeareaview> 
  );
}
Enter fullscreen mode Exit fullscreen mode

In this code sample, we procured the user’s file paths from the react-native-fs library. Later on, we then stored these values into the downloadsFolder, documentsFolder, and externalFolder Hooks. In the end, the program rendered the Hooks onto the screen.
The Program Rendered The Hooks Onto The Screen

Reading directories

To get files and folder content, RNFS bundles a [readDir](https://github.com/itinance/react-native-fs) method. As the name suggests, this function allows developers to get statistics of a certain folder:

function App() {
  const [files, setFiles] = useState([]);

  const getFileContent = async (path) => {
    const reader = await RNFS.readDir(path);
    setFiles(reader);
  };
  useEffect(() => {
    getFileContent(RNFS.DocumentDirectoryPath); //run the function on the first render.
  }, []);
  //this component will render our list item to the UI
  const Item = ({ name, isFile }) => {
    return (
      <view><text style="{styles.name}">Name: {name}</text>
        <text> {isFile ? "It is a file" : "It's a folder"}</text></view> 
    );
  };
  const renderItem = ({ item, index }) => {
    return (
      <view>
        <text style="{styles.title}">{index}</text>
        {/* The isFile method indicates whether the scanned content is a file or a folder*/}
        </view>
    );
  };
  return (
    <safeareaview>
      <flatlist data="{files}" renderitem="{renderItem}" keyextractor="{(item)" =="">item.name}
      /></flatlist> </safeareaview>
  );
}
Enter fullscreen mode Exit fullscreen mode

Here’s a breakdown of this code piece by piece:

  • In the beginning, we declared an asynchronous function called getFileContent
  • The getFileContent method executes the readDir method with the argument set to path. This means that the project will read the path directory and return all the available content as an array
  • Later on, we stored the value of the response into the files Hook
  • Furthermore, the program executed the getFileContent function and passed in the RNFS.DocumentDirectoryPath constant as an argument. This means that React Native will now try to read the contents of our app’s data folder
  • In the end, we used the [FlatList](https://blog.logrocket.com/deep-dive-react-native-flatlist/) module to render the value of the files in a list view Render The Values Of Files In List View

Advanced usage

Creating folders

Directories are crucial for organizational purposes. For example, all images should go into the assets folder, and the user data should stay in the appdata directory.

To materialize a folder, RNFS includes a function called [mkdir](https://github.com/itinance/react-native-fs#mkdirfilepath-string-options-mkdiroptions-promisevoid). Here’s a brief example of this method in action:

const folderPath = RNFS.DocumentDirectoryPath + "/assets";

const makeDirectory = async (folderPath) => {
  await RNFS.mkdir(folderPath); //create a new folder on folderPath
};

useEffect(() => {
  makeDirectory(folderPath); //execute this function on first mount
  getFileContent(RNFS.DocumentDirectoryPath); //this function was defined in the previous example
}, []);
return (
  <safeareaview>
    {/*FlatList code to render file paths.*/}
    {/*renderItem function was defined earlier in this article*/}
    <flatlist data="{files}" renderitem="{renderItem}" keyextractor="{(item)" =="">item.name}
    /></flatlist> </safeareaview>
);
Enter fullscreen mode Exit fullscreen mode

In this piece of code, our makeDirectory method accepts a parameter called folderPath. When invoked, the app runs the mkdir function, which then creates a new folder at the specified path.
Run The Mkdir Function

Creating files

To write content to a file, RNFS includes a [writeFile](https://github.com/itinance/react-native-fs#writefilefilepath-string-contents-string-encoding-string-promisevoid) method. This is critical for use cases where the app has to store sensitive user data on the user’s device:

const filePath = RNFS.DocumentDirectoryPath + "/joke.txt"; //absolute path of our file
const fileContent = "Why do programmers wear glasses? \n They can't C#!";

const makeFile = async (filePath, content) => {
  try {
    //create a file at filePath. Write the content data to it
    await RNFS.writeFile(filePath, content, "utf8");
    console.log("written to file");
  } catch (error) { //if the function throws an error, log it out.
    console.log(error);
  }
};
//extra code removed for brevity..
useEffect(() => {
  makeFile(filePath, fileContent);
  getFileContent(RNFS.DocumentDirectoryPath);
}, []);
return {
  /* Code to render FlatList with files Hook as our dataset...*/
};
Enter fullscreen mode Exit fullscreen mode

In this snippet, we first coded a custom function called makeFile, which takes in two parameters: filePath and content. Within this function, we are invoking the RNFS.writeFile method, which tells React to create a file at filePath and write the value of content to this desired entity.
Create Filepath

Reading files

RNFS’s [readFile](https://github.com/itinance/react-native-fs#readfilefilepath-string-encoding-string-promisestring) function allows developers to procure data from a chosen file. This is important for note-taking apps, where the app has to read plain text files from the disk and display them to the user:

const filePath = RNFS.DocumentDirectoryPath + "/joke.txt";
const [fileData, setFileData] = useState();

const readFile = async (path) => {
  const response = await RNFS.readFile(path);
  setFileData(response); //set the value of response to the fileData Hook.
};
useEffect(() => {
  readFile(filePath);
}, []);

return (
  <safeareaview>{/* Display the value*/}
    <text style="{styles.name}">{fileData}</text></safeareaview> 
);
Enter fullscreen mode Exit fullscreen mode

When invoked, the RNFS.readFile function will attempt to get the contents of the file located in our chosen directory. If the attempt fails, the program will crash and throw an error. Error In Program

File deletion

In order to remove a file, you can use the [unlink](https://github.com/itinance/react-native-fs#unlinkfilepath-string-promisevoid) function like so:

const folderPath = RNFS.DocumentDirectoryPath + "/assets"; //path of folder to delete
const filePath = RNFS.DocumentDirectoryPath + "/joke.txt"; //file to delete
const [files, setFiles] = useState([]);

const deleteFile = async (path) => {
  try {
    await RNFS.unlink(path); //delete the item present at 'path'
    console.log("file deleted");
  } catch (error) {
    console.log(error);
  }
};
useEffect(() => {
  //delete both the joke.txt file and the assets folder 
  deleteFile(filePath); 
  deleteFile(folderPath);
  //when the files and folders are deleted, get available files and folders:
  getFileContent(RNFS.DocumentDirectoryPath);
}, []);
return <safeareaview>{/*Code to render FlatList..*/}</safeareaview>;
Enter fullscreen mode Exit fullscreen mode

In this block of code, we used the unlink method to delete a file and a folder from the document directory.
Used The Unlink Method To Delete A File And A Folder

Conclusion

Here is the source code for the article.

In this article, you learned how to create files and directories and write to them via the react-native-fs library. Other than file modification, we can use this library for other situations, for example:

  • Online storage apps: Cloud storage services like Google Drive and Tresorit upload the clients’ files located on their mobile devices
  • Email: When it comes to sending attachments to a receiver, email clients allow the user to select and send files using a file manager

If you encountered any difficulty, I encourage you to play with and deconstruct the code so that you can fully understand its inner workings.

Thank you so much for making it to the end! Happy coding!


LogRocket: Instantly recreate issues in your React Native apps.

[LogRocket Signup

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — try LogRocket for free.

Top comments (0)