Working with AsyncStorage for Local Data Persistence

AsyncStorage is a simple, unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It's widely used in React Native for storing data locally on the device.

July 19, 20243 min read

AsyncStorage is a simple, unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It's widely used in React Native applications for storing data locally on the device. In this article, we'll explore how to use AsyncStorage effectively for local data persistence.

Introduction to AsyncStorage

AsyncStorage provides a way to store string data in a key-value format. It's asynchronous, meaning all operations return a Promise. It's important to note that AsyncStorage is not encrypted and should not be used to store sensitive information.

Basic Operations with AsyncStorage

Try Kodaschool for free

Click below to sign up and get access to free web, android and iOs challenges.

Sign Up

Importing AsyncStorage

First, you need to import AsyncStorage:

import AsyncStorage from '@react-native-async-storage/async-storage';
Note: In newer versions of React Native, AsyncStorage has been moved to a separate package. You may need to install it:
npm install @react-native-async-storage/async-storage

Storing Data

To store a string value:

const storeData = async (key, value) => {
  try {
    await AsyncStorage.setItem(key, value);
  } catch (e) {
    // saving error
    console.error('Error storing data:', e);
  }
};

To store an object, you need to stringify it first:

const storeObjectData = async (key, value) => {
  try {
    const jsonValue = JSON.stringify(value);
    await AsyncStorage.setItem(key, jsonValue);
  } catch (e) {
    // saving error
    console.error('Error storing object data:', e);
  }
};

Retrieving Data

To retrieve a string value:

const getData = async (key) => {
  try {
    const value = await AsyncStorage.getItem(key);
    if (value !== null) {
      // value previously stored
      return value;
    }
  } catch (e) {
    // error reading value
    console.error('Error retrieving data:', e);
  }
};

To retrieve an object:

const getObjectData = async (key) => {
  try {
    const jsonValue = await AsyncStorage.getItem(key);
    return jsonValue != null ? JSON.parse(jsonValue) : null;
  } catch (e) {
    // error reading value
    console.error('Error retrieving object data:', e);
  }
};

Removing Data

To remove an item:

const removeData = async (key) => {
  try {
    await AsyncStorage.removeItem(key);
  } catch (e) {
    // remove error
    console.error('Error removing data:', e);
  }
};

Advanced Usage

Storing Multiple Items

You can store multiple key-value pairs at once:

const storeMultipleData = async () => {
  const firstPair = ["@MyApp_user", "user_1"]
  const secondPair = ["@MyApp_key", "key_1"]
  try {
    await AsyncStorage.multiSet([firstPair, secondPair])
  } catch(e) {
    //save error
    console.error('Error storing multiple items:', e);
  }
};

Retrieving Multiple Items

Similarly, you can retrieve multiple items:

const getMultipleData = async () => {
  let values
  try {
    values = await AsyncStorage.multiGet(['@MyApp_user', '@MyApp_key'])
  } catch(e) {
    // read error
    console.error('Error retrieving multiple items:', e);
  }
  // values = [['@MyApp_user', 'user_1'], ['@MyApp_key', 'key_1']]
};

Merging Data

For objects, you can merge new data with existing data:

const mergeData = async () => {
  try {
    await AsyncStorage.mergeItem('@MyApp_user', JSON.stringify({
      age: 30,
      token: 'abc'
    }))
  } catch(e) {
    // merge error
    console.error('Error merging data:', e);
  }
};

Practical Example: User Preferences

Here's a practical example of using AsyncStorage to store and retrieve user preferences:

import React, { useState, useEffect } from 'react';
import { View, Switch, Text } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';

const UserPreferences = () => {
  const [isDarkMode, setIsDarkMode] = useState(false);

  useEffect(() => {
    // Load the user's preference when the component mounts
    loadDarkModePreference();
  }, []);

  const loadDarkModePreference = async () => {
    try {
      const value = await AsyncStorage.getItem('@dark_mode');
      if (value !== null) {
        setIsDarkMode(JSON.parse(value));
      }
    } catch (e) {
      console.error('Error loading dark mode preference:', e);
    }
  };

  const saveDarkModePreference = async (value) => {
    try {
      await AsyncStorage.setItem('@dark_mode', JSON.stringify(value));
      setIsDarkMode(value);
    } catch (e) {
      console.error('Error saving dark mode preference:', e);
    }
  };

  return (
    <View>
      <Text>Dark Mode</Text>
      <Switch
        value={isDarkMode}
        onValueChange={saveDarkModePreference}
      />
    </View>
  );
};

export default UserPreferences;

Best Practices

  • Error Handling: Always wrap AsyncStorage operations in try-catch blocks to handle potential errors.
  • Use Prefixes: Use prefixes for your keys (e.g., '@MyApp_') to avoid conflicts with other data stored on the device.
  • Avoid Storing Sensitive Data: AsyncStorage is not encrypted. Don't use it for sensitive information like passwords or tokens.
  • Batch Operations: When possible, use multiSet and multiGet to perform batch operations, which can be more efficient.
  • Handle Initial App Load: Remember to handle the initial app load when no data has been stored yet.
  • Migrate to Better Solutions for Complex Data: For more complex data structures or larger amounts of data, consider using SQLite or other more robust storage solutions.

AsyncStorage is a powerful tool for persisting data locally in React Native applications. It's simple to use and can greatly enhance the user experience by allowing apps to remember user preferences and other non-sensitive data. By following the best practices and understanding its limitations, you can effectively leverage AsyncStorage in your React Native projects.

Remember, while AsyncStorage is great for many use cases, always consider the nature of the data you're storing and choose the appropriate storage method for your specific needs.

Cliff Gor

About Cliff Gor

As a Fullstack Software Engineer, I design and develop user-centric and robust systems and applications using HTML, CSS, Bootstrap, React Js, React Native, and Kotlin(Android).