Mastering React Native Async Storage: What It Is and How to Use It

What is React Native Async Storage and How to Use It How Does React Native Async Storage Work

When building mobile apps, one key aspect that developers must consider is how to make their apps remember data. Even after the app has been closed or restarted, this capability ensures a seamless user experience and ongoing data management. React Native, a popular framework for cross-platform app development addresses this need by providing community-maintained packaged Async Storage. React Native Async Storage stands out as an effective and lightweight tool for handling simple key-value data pairs. This blog post explores what React Native Async Storage is and provides a step-by-step guide on how to implement it and use it efficiently in projects.

Understanding React Native Async Storage

Async Storage is a simple yet powerful key-value storage system in React Native. You can think of it as an asynchronous, mobile counterpart of web localStorage. It allows the app to save and retrieve small amounts of data like user preferences, simple app settings, or cached data for offline functionality. In older React Native versions, it came included in projects by default, but now it is a community-maintained package.[^1] 

Async Storage’s straightforward API makes it accessible to developers, providing essential functions like storing, retrieving, deleting, or clearing all data to easily manage information. This simplicity is balanced by its non-blocking, asynchronous nature, which ensures that data operations do not interfere with the main thread or app performance. Although primarily suited for storing lightweight data, Async Storage can be used to store more complex data structures, such as JSON objects. Leveraging Async Storage, React Native developers can create apps with improved offline capabilities and a more seamless user experience, ensuring that important data is retained between sessions.

How Does React Native Async Storage Work?

Async Storage is persistent storage, which means that data saved there is stored on the device’s physical memory and remains available across app launches. This makes it a perfect solution for storing data that should be kept, regardless of whether the mobile app is active, inactive, or not running at all.

Key-Value Pair Storage System

Async Storage operates on a simple key-value pair storage system, similar to JavaScript’s localStorage but with added capabilities for mobile environments. Each piece of data is linked to a unique key, a string used as an identifier to store, retrieve, or delete the data. The value is also stored as a string, meaning developers should serialize more complex data structures like arrays or objects using JSON.stringify() and parse them back with JSON.parse() upon retrieval. This approach allows for flexibility in data storage while maintaining simplicity. For instance, an app can store a user's preferred language as a key-value pair such as (preferredLanguage, English), enabling it to quickly access and apply the setting when the app is reopened.

Data Persistance

Another main feature of Async Storage is its ability to persist data, meaning that data stored remains available even after the app is closed or the device is restarted. Stored locally on the device's file system and separate from the app's volatile memory—cleared when the app restarts—Async Storage ensures that user preferences, small caches, or other important non-volatile data stay consistent across sessions. This feature is essential for user experience; for example, storing a user’s onboarding status enables an app to remember whether the user has completed the initial walkthrough or tutorial.

Async Functioning

Async Storage functions asynchronously, not blocking the app's main thread while reading or writing data. It is essential for app performance and responsiveness, especially on devices with limited resources. Because the operations are asynchronous, React Native developers interact with Async Storage using Promises or async/await syntax. This helps keep the app's UI smooth and fluid, as data operations do not cause delays or freezing.

React Native Async Storage: Use Cases, Limitations, and Security Considerations

Common use cases of Async Storage include storing language or theme settings. It can also be used to support offline mode in mobile apps. Libraries such as TanStack Query use Async Storage to support that functionality.[^2] However, it is important to remember that React Native Async Storage has limitations when it comes to the size of stored data. For larger or more complex data requirements, such as heavy relational data or large file storage, developers should consider using other solutions like SQLite or Realm.

Since Async Storage preserves data across sessions, it might seem ideal for storing items like login tokens, which help an app maintain authentication and avoid repeated logins. While it's intuitive to store tokens on the user’s device to improve the experience, Async Storage is not a secure option for sensitive information like login tokens. It’s also important to know that Async Storage is unencrypted. This means that even though each app has its own Async Storage sandbox, storing sensitive information there is unsafe.[3] Data such as tokens or secrets should not be placed in it. Later in the article, in the section on "Secure Storage in React Native," we cover where to store confidential data safely.

Setting Up React Native Async Storage: Step-by-Step Guide

Follow this Async Storage React Native tutorial to set up the tool smoothly and use it in your React Native app or Expo project. The process is straightforward.

Let's start by installing the library. Run the following command in your project directory (you can also add it to your Expo project):

npm install @react-native-async-storage/async-storage

Importing Async Storage:

import AsyncStorage from '@react-native-async-storage/async-storage';

When using the library, there is one important thing to remember — Async Storage can only store string data. So, if you need to store a JSON object, remember to serialize it first.

How to use Async Storage in React Native

Using async storage is quite simple. Below are three functions that cover the most common use cases: saving, retrieving, and removing data. Leveraging them will definitely improve the user experience with data persistence and offline support.

Saving data to Async Storage:

async function saveDataToAsyncStorage(key: string, data: SomeData) {
     try { 
         if (data) { 
             await AsyncStorage.setItem(key, JSON.stringify(data)); 
        } 
     } catch (error) { // handle error } 
}   

Getting data from Async Storage:

async function getDataFromAsyncStorage(key: string) { 
     try { 
         const data = await AsyncStorage.getItem(key); 

         // if your data was an json object remember to parse it 
         if (data) { return JSON.parse(data); } 
     } catch (error) { // handle error } 
}  

Removing data from Async Storage

async function clearAsyncStorage(key: string) { 
     try { 
         await AsyncStorage.removeItem(key); 
     } catch (error) { // handle error }
} 

By following these steps, you can effectively implement and manage data storage in your React Native app. However, if the functions presented are insufficient for your use case, Async Storage has great documentation on their API

There is also an ongoing discussion about Async Storage hook implementation on Github that is worth checking out if you’d like to dive deeper into the subject.

Where is data stored in Async Storage kept on the device?

Definitely not inside the application. On iOS, there are two possible locations where data saved to Async Storage can be stored. If data does not exceed 1024 characters, it is stored in a common manifest.json file; if it is bigger, it is stored in individual, dedicated files.[^4] 

On Android, all the data stored in Async Storage is saved in the phone's SQLite database. 

There are also some restrictions on how much data and big entries can be kept in Async Storage. This is mainly because of some limitations in SQLite's storage capacity. The default limit is 6 MB for the total amount of data and 2 MB per record. The Async Storage library allows users to adjust the total storage size by setting an AsyncStorage_db_size_in_MB flag.[^5] However, it is important to keep in mind that the available space on the device's memory should not be exceeded when testing the limit.

Secure Storage in React Native

As mentioned earlier in the article, sensitive information, such as user tokens, should not be stored in Async Storage. So, where should it be stored? The short answer is in one of the dedicated React Native libraries. There are several options, such as expo-secure-storage or react-native-keychain. 

While their APIs look almost identical to Async Storage API, it's good to know they are different under the hood. These libraries keep the data in a dedicated, encrypted place specifically designed for sensitive information. This ensures that the data is securely stored within the system and prevents other apps on the device from accessing it. On iOS, data saved in the secure storage is kept in Keychain Services and Secured Shared Preferences on Android.[^6]

The Benefits of Using React Native Async Storage

React Native Async Storage is essential for managing persistent data in their mobile apps. Its simplicity makes it easy to implement, especially for small-scale data storage needs, allowing developers to focus on building features without troubling their heads with complex storage solutions. The asynchronous API ensures that data operations are non-blocking, which keeps the app’s performance smooth and responsive. With cross-platform support, Async Storage works seamlessly on iOS and Android, making it a reliable choice for consistent user experiences across devices. Perhaps most importantly, its data persistence ensures that crucial information remains intact even after the app restarts or updates. By incorporating Async Storage into React Native projects, it is possible to elevate the functionality and reliability of apps, providing users with a seamless and dependable experience.

Barbara Banaszak
Barbara Banaszak
Javascript Developer at Monterail