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:
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
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:
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
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 folderDownloadDirectoryPath
: Points toward the user’s Downloads
directoryExternalStorageDirectory
: Contains the path of the device’s external storageHere’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.
To get files and folder content, RNFS bundles a readDir
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*/} <Item name={item.name} isFile={item.isFile()} /> </View> ); }; return ( <SafeAreaView> <FlatList data={files} renderItem={renderItem} keyExtractor={(item) => item.name} /> </SafeAreaView> ); }
Here’s a breakdown of this code piece by piece:
getFileContent
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 arrayfiles
HookgetFileContent
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 folderFlatList
module to render the value of the files
in a list viewDirectories 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
. 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} /> </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.
To write content to a file, RNFS includes a writeFile
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.
RNFS’s readFile
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.
In order to remove a file, you can use the unlink
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.
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:
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 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.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowEfficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
Design React Native UIs that look great on any device by using adaptive layouts, responsive scaling, and platform-specific tools.
Angular’s two-way data binding has evolved with signals, offering improved performance, simpler syntax, and better type inference.
Fix sticky positioning issues in CSS, from missing offsets to overflow conflicts in flex, grid, and container height constraints.
One Reply to "How to access file systems with React Native"
It is not working in latest react native 0.70
Everytime i install (all steps are followed according to documentation), project got crashed.