Skip to main content
React Native Introduction
CHAPTER 20 Beginner

AsyncStorage and Local Data Storage

Updated: May 16, 2026
7 min read

# CHAPTER 20

AsyncStorage and Local Data Storage

1. Introduction

If a user flips a switch to enable "Dark Mode" in your app, they expect that setting to remain true when they open the app tomorrow. However, React State and Redux are stored in the device's volatile RAM. The millisecond the app is swiped away and killed, the RAM is wiped clean, and all state resets to default. To remember settings permanently, you must write data directly to the phone's physical hard drive. In this chapter, we will master AsyncStorage and Local Data Storage. We will install the official package to easily read, write, and delete Key-Value pairs, allowing our app to remember user preferences and securely maintain login sessions.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Install and configure the @react-native-async-storage/async-storage package.
  • Write Strings and JSON Objects to the physical hard drive.
  • Read stored data asynchronously upon application startup.
  • Delete and wipe stored preferences.
  • Understand the security limitations of plain-text local storage.

3. What is AsyncStorage?

AsyncStorage is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It wraps the native storage systems of the operating system (Android SharedPreferences and iOS NSUserDefaults).
  • Key: "username" -> Value: "Alice"
  • Key: "high_score" -> Value: "450"

*Important Rule: AsyncStorage can ONLY store Strings. You cannot store Integers, Booleans, or raw Objects directly. Everything must be stringified!*

4. Installation

Historically, this was built into React Native. It has since been extracted to a community package. Run the following command in your terminal:
bash
1
npx expo install @react-native-async-storage/async-storage

5. Saving Data (Writing to Disk)

Writing to a physical hard drive takes time. Therefore, every method in AsyncStorage is a Promise, meaning we MUST use async/await.
javascript
123456789101112
import AsyncStorage from '@react-native-async-storage/async-storage';

// Function to save a simple string
const saveThemePreference = async (value) => {
  try {
    // Requires a Key ('@theme') and a Value!
    await AsyncStorage.setItem('@theme', value);
    console.log("Theme saved successfully!");
  } catch (e) {
    console.error("Failed to save data to disk.");
  }
};

What if we want to save a complex Object (like a User Profile)? We MUST use JSON.stringify().

javascript
12345678
const saveUser = async (userObj) => {
  try {
    const jsonValue = JSON.stringify(userObj); // Convert Object to String
    await AsyncStorage.setItem('@user_profile', jsonValue);
  } catch (e) {
    console.error("Failed to save user object.");
  }
};

6. Loading Data (Reading from Disk)

When the app launches, we want to grab the saved theme to display it. If the app has never been opened before, the data won't exist, and the method will return null.
javascript
123456789101112131415
const loadThemePreference = async () => {
  try {
    const value = await AsyncStorage.getItem('@theme');
    
    if (value !== null) {
      console.log("Retrieved theme from disk:", value); // e.g., "dark"
      return value;
    } else {
      console.log("No theme saved yet. Defaulting to light.");
      return "light";
    }
  } catch (e) {
    console.error("Failed to fetch data.");
  }
};

When reading an Object, we MUST use JSON.parse() to turn the string back into usable JavaScript!

javascript
1234
const loadUser = async () => {
  const jsonValue = await AsyncStorage.getItem('@user_profile');
  return jsonValue != null ? JSON.parse(jsonValue) : null;
};

7. Deleting Data

When a user clicks "Log Out", you must delete their stored data from the hard drive.
javascript
12345678910111213
const logOutUser = async () => {
  try {
    // Remove a specific key
    await AsyncStorage.removeItem('@user_profile');
    
    // OR: Wipe the ENTIRE storage clean! (Use with caution)
    // await AsyncStorage.clear(); 
    
    console.log("User logged out and data wiped.");
  } catch (e) {
    console.error("Failed to clear data.");
  }
};

8. Integrating with the UI (useEffect)

We combine AsyncStorage with useEffect to fetch the data the exact millisecond the screen opens.
javascript
12345678910111213141516171819202122232425262728293031323334
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';

export default function NotesApp() {
  const [note, setNote] = useState('');

  // 1. Run ONCE when the app opens to load the saved note
  useEffect(() => {
    loadNote();
  }, []);

  const loadNote = async () => {
    const savedNote = await AsyncStorage.getItem('@my_note');
    if (savedNote) setNote(savedNote);
  };

  const saveNote = async () => {
    await AsyncStorage.setItem('@my_note', note);
    alert("Note saved permanently!");
  };

  return (
    <View style={{ padding: 50 }}>
      <Text style={{ fontSize: 20 }}>My Sticky Note:</Text>
      <TextInput 
        style={{ borderWidth: 1, padding: 10, marginVertical: 20 }}
        value={note}
        onChangeText={setNote}
      />
      <Button title="Save Note" onPress={saveNote} />
    </View>
  );
}

9. Common Mistakes

  • Storing Sensitive Data: AsyncStorage saves data in plain-text XML files on the phone. Do NOT store raw passwords, credit card numbers, or secure encryption keys here! A rooted/jailbroken phone can easily read these files. For highly sensitive data, use expo-secure-store, which encrypts the data using the native iOS Keychain and Android Keystore.

10. Best Practices

  • Define Keys as Constants: If you misspell '@user_profile' as '@userprofile' when trying to read the data, it will return null and drive you insane tracking down the bug. Always define your keys as constants at the top of an API file: export const KEYS = { USER_PROFILE: '@user_profile' }; and use AsyncStorage.getItem(KEYS.USER_PROFILE) to eliminate typo bugs.

11. Practice Exercises

  1. 1. What official package is required to save persistent Key-Value pairs to the mobile device's physical storage?
  1. 2. What JavaScript function MUST be utilized before attempting to pass a complex Object (like { id: 1, name: 'Bob' }) into the AsyncStorage.setItem() method?

12. MCQs with Answers

Question 1

Because writing to physical flash memory is significantly slower than writing to RAM, how is the AsyncStorage API architected?

Question 2

When attempting to read a key via AsyncStorage.getItem('@highScore'), what does the method return if the user has never opened the app before and the key does not exist on the hard drive?

13. Interview Questions

  • Q: Explain the mechanical flow of persisting and retrieving a complex JavaScript Object (e.g., a Shopping Cart Array) using AsyncStorage. Detail the serialization and deserialization steps required.
  • Q: Contrast AsyncStorage with SecureStore (or react-native-keychain). What are the specific security implications of AsyncStorage, and what specific data types mandate the use of encrypted storage solutions?
  • Q: Describe how you would utilize the useEffect hook in the root App.js component to check AsyncStorage for an existing authentication token to determine whether to route the user to the Login screen or the Home screen.

14. FAQs

Q: Is there a storage limit for AsyncStorage? A: Yes. On Android, it is traditionally capped around 6MB. It is designed for small configuration strings and tokens. Do NOT try to store a 10MB Base64 image string or an offline cache of 10,000 chat messages here. For large datasets, use a true database like SQLite!

15. Summary

In Chapter 20, we bestowed our application with permanent memory. We moved beyond the ephemeral nature of RAM and utilized AsyncStorage to write data directly to the device's physical hard drive. We mastered the asynchronous workflow required for disk operations, writing data using setItem() and reading it securely upon app launch via useEffect and getItem(). We bridged the String-only limitation by serializing objects using JSON.stringify(), and established strict security protocols regarding plain-text storage vulnerabilities.

16. Next Chapter Recommendation

We know how to fetch a token from a server, and we know how to save it permanently to the hard drive. It is time to combine these skills to build a real security flow. Proceed to Chapter 21: Authentication in React Native.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·