React Native AsyncStorage with Expo

Last update: 2025-04-24
Type
Quick Win's logo Quick Win
Membership
🆓
Tech
Share:

AsyncStorage is a crucial part of React Native development, allowing you to persist data locally on the device. In this quick win, we’ll explore how to implement AsyncStorage in your Expo React Native applications effectively.

Setting Up AsyncStorage

First, install the required package in your Expo project:

npx expo install @react-native-async-storage/async-storage

This command will install the official AsyncStorage package that’s compatible with your Expo version. Using npx expo install instead of npm install ensures you get a version that works with your current Expo SDK.

Basic Usage

1. Storing Data

AsyncStorage works with key-value pairs and requires async/await syntax. Here’s how to store data:

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

const storeData = async (key, value) => {
	try {
		await AsyncStorage.setItem(key, JSON.stringify(value));
		console.log('Data stored successfully');
	} catch (error) {
		console.error('Error storing data:', error);
	}
};

// Example usage
const userData = {
	name: 'John Doe',
	email: 'john@example.com'
};
await storeData('user', userData);

Let’s break this down:

  • AsyncStorage.setItem() takes two parameters: a key (string) and a value (string)
  • Since AsyncStorage only stores strings, we use JSON.stringify() to convert objects into strings
  • The function is wrapped in a try-catch block to handle potential storage errors
  • We use async/await because storage operations are asynchronous

2. Retrieving Data

Here’s how to retrieve stored data:

const getData = async (key) => {
	try {
		const value = await AsyncStorage.getItem(key);
		return value ? JSON.parse(value) : null;
	} catch (error) {
		console.error('Error retrieving data:', error);
		return null;
	}
};

This retrieval function:

  • Uses AsyncStorage.getItem() to fetch data by its key
  • Converts the stored string back to an object using JSON.parse()
  • Returns null if no data is found or if there’s an error
  • Includes error handling for failed operations

3. Practical Component Example

Here’s a complete example of a user preferences component that implements dark mode toggling:

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

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

	useEffect(() => {
		loadPreferences();
	}, []);

	const loadPreferences = async () => {
		try {
			const savedMode = await AsyncStorage.getItem('darkMode');
			if (savedMode !== null) {
				setIsDarkMode(JSON.parse(savedMode));
			}
		} catch (error) {
			console.error('Error loading preferences:', error);
		}
	};

	const toggleDarkMode = async (value) => {
		try {
			await AsyncStorage.setItem('darkMode', JSON.stringify(value));
			setIsDarkMode(value);
		} catch (error) {
			console.error('Error saving preference:', error);
		}
	};

	return (
		<View style={styles.container}>
			<Text style={styles.text}>Dark Mode</Text>
			<Switch value={isDarkMode} onValueChange={toggleDarkMode} />
		</View>
	);
};

const styles = StyleSheet.create({
	container: {
		flexDirection: 'row',
		alignItems: 'center',
		padding: 16
	},
	text: {
		marginRight: 10,
		fontSize: 16
	}
});

export default UserPreferences;

This component demonstrates several key concepts:

  • Uses useState to manage the dark mode state
  • Loads saved preferences when the component mounts using useEffect
  • Implements a toggle function that both updates the state and saves to AsyncStorage
  • Provides a simple UI with a Switch component for user interaction
  • Includes proper error handling for all storage operations

Advanced Features

1. Multiple Items Operations

When you need to store multiple items at once:

const storeMultipleItems = async () => {
	try {
		await AsyncStorage.multiSet([
			['@user_name', 'John'],
			['@user_age', '30']
		]);
	} catch (error) {
		console.error('Error storing multiple items:', error);
	}
};

The multiSet method:

  • Takes an array of key-value pair arrays
  • Performs all storage operations atomically
  • Uses the recommended ’@’ prefix for keys
  • Is more efficient than multiple individual setItem calls

2. Removing Data

To remove specific items from storage:

const removeData = async (key) => {
	try {
		await AsyncStorage.removeItem(key);
		console.log('Data removed successfully');
	} catch (error) {
		console.error('Error removing data:', error);
	}
};

This removal function:

  • Completely removes the key-value pair from storage
  • Returns successfully even if the key doesn’t exist
  • Should be used when you no longer need specific data
  • Includes error handling for failed operations

3. Clearing All Data

For clearing the entire storage:

const clearAll = async () => {
	try {
		await AsyncStorage.clear();
		console.log('Storage cleared successfully');
	} catch (error) {
		console.error('Error clearing storage:', error);
	}
};

The clear operation:

  • Removes all keys and values from AsyncStorage
  • Should be used carefully, typically during logout or reset
  • Is useful for debugging or implementing a “reset app” feature
  • Cannot be undone once executed

Best Practices

  1. Error Handling: Always implement proper error handling with try-catch blocks
  2. Data Structure: Use consistent key naming conventions (e.g., ‘@app_name_key’)
  3. JSON Conversion: Remember to stringify objects when storing and parse when retrieving
  4. Async Operations: Handle loading states appropriately in your UI
  5. Memory Usage: Be mindful of storage limits and clean up unused data

Common Use Cases

  • User preferences
  • Authentication tokens
  • App settings
  • Cached API responses
  • Form data persistence
  • Offline data storage

Summary

AsyncStorage is a powerful tool for local data persistence in React Native and Expo applications. By following these patterns and best practices, you can effectively manage local data storage in your mobile apps.

Remember to:

  • Always handle async operations properly
  • Implement error handling
  • Use consistent key naming
  • Be mindful of storage limitations
  • Clean up unused data regularly

Now you’re ready to implement robust local storage in your Expo React Native apps! 🚀

Zero to Hero React Native Mission
Simon Grimm