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:
Here are the steps we’ll take:
- Getting started
- Basic usage
- Getting file paths
- Reading directories
- Advanced Usage
- Creating folders
- Creating files
- Reading files
- File deletion
Getting started
As a first step, we have to initialize a React Native project using react-native-cli
like so:
react-native init fileSystemLearn
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
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’sDownloads
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>
);
}
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.
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>
);
}
Here’s a breakdown of this code piece by piece:
- In the beginning, we declared an asynchronous function called
getFileContent
- The
getFileContent
method executes thereadDir
method with the argument set topath
. This means that the project will read thepath
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 theRNFS.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 thefiles
in a 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>
);
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.
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...*/
};
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.
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>
);
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.
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>;
In this block of code, we used the unlink
method to delete a file and a folder from the document directory.
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 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)