DEV Community

Cover image for What is AsyncStorage in React Native?
Aman Mittal
Aman Mittal

Posted on • Updated on • Originally published at instamobile.io

What is AsyncStorage in React Native?

Cover Image Credits to Unsplash and Tom Pumford

AsyncStorage is a simple, asynchronous key-value pair used in React Native applications. It’s used for a variety of scenarios but mainly to store data when your app is not using any cloud services, or when you want to implement features in your app that require data storage.

It operates globally in a React Native app and comes with its own limitations. As a React Native developer, you have to know what these limitations are. One limitation of an AsyncStorage API is that on Android the size of the database is set to a default of 6MB limit. Also, AsyncStorage storage is based on SQLite.

Thus, it’s important to keep SQLite limitations in mind, too. Also, it’s hard to store complex and nested data structures in the form of key-value pairs. Knowing about these limitations will help you to opt for the best solution when developing a mobile app.

According to the React Native’s official documentation:

On iOS, AsyncStorage is backed by native code that stores small values in a serialized dictionary and larger values in separate files. On Android, AsyncStorage will use either RocksDB or SQLite based on what is available.

Create an Expo app

To get started, you’ll need to generate a new Expo project. This could be done by opening a terminal window, navigating to a suitable location where you develop projects, and running the following commands in the order they’re described.

expo init offline-app

# navigate inside the app folder
cd offline-app
Enter fullscreen mode Exit fullscreen mode

Note: yarn is currently being used as the package manager. You can also use npm instead of yarn.

Utilizing the AsyncStorage API

In this section, let’s build an app that saves a value to AsyncStorage and fetches the value from the storage in the client-side React Native app. This will help you learn how to write basic operations using the storage API. Lastly, you’ll learn about how to clear the storage completely.

Open the App.js file and add the snippet below. Start by importing the necessary components from the React Native API. The most important one here is AsyncStorage. After that, define a variable named STORAGE_KEY. This variable will be used to store and retrieve the stored data using the AsyncStorage API.

Think of it as an identifier for the value being stored or the name of the key in the key-value pair. Since you’re going to store only one value at the moment, there’s only the requirement for one key.

import React from 'react'
import { StyleSheet, Text, View, TextInput, AsyncStorage, TouchableOpacity } from 'react-native'

const STORAGE_KEY = '@save_name'
Enter fullscreen mode Exit fullscreen mode

Next, let’s define an initial state with two empty strings. They’re going to be used to save the value of the user input and then retrieve the value to display it on the app screen. After defining the initial state, there’s going to be a lifecycle method that will load the data when the application starts for the first time, or when the App component renders.

class App extends React.Component {
  state = {
    text: '',
    name: ''
  }

  componentDidMount() {
    this.retrieveData()
  }

  // ...
}  
Enter fullscreen mode Exit fullscreen mode

In the above snippet, note that the App component is actually a class component and not the default functional component that comes with boilerplate Expo app.

Read the data

There are three asynchronous methods that will help to store the data, retrieve the data, and clear the app data that are stored. Each of these methods is going to utilize the appropriate API method from the AsyncStorage API. Every method in the AsyncStorage API is promise-based; hence, let’s use async/await syntax to follow best practices.

retrieveData = async () => {
    try {
      const name = await AsyncStorage.getItem(STORAGE_KEY)

      if (name !== null) {
        this.setState({ name })
      }
    } catch (e) {
      alert('Failed to load name.')
    }
  }
Enter fullscreen mode Exit fullscreen mode

In the above snippet, the name of the method implies what it’s going to do in the app. The retrieveData method is what fetches the data from storage if it exists. It uses the same identifier that you defined previously, outside the class function component. It utilizes the parameter in the state object name.

Note that there’s an if condition inside this method. This condition makes sure that data is fetched only when a value for the name variable exists. This method also uses try/catch, as they are part and parcel of writing functions with modern async/await syntax. Lastly, this method is being invoked inside the lifecycle method.

Save the Data

The next function is going to save the data. In the below snippet, you’ll find that it uses a parameter name, which, on success, is the value that’s stored. An alert message will be shown when the input data is saved.

save = async name => {
    try {
      await AsyncStorage.setItem(STORAGE_KEY, name)
      alert('Data successfully saved!')
      this.setState({ name })
    } catch (e) {
      alert('Failed to save name.')
    }
  }
Enter fullscreen mode Exit fullscreen mode

Remove Everything

The last method that you are going to utilize from the AsyncStorage API is called clear(). This deletes everything that is previously saved. It is not recommended to use this method directly if you want to delete only a specific item from the storage. For that, there are methods like removeItem or multiRemove available by the API. You can read more about them in the official documentation here or later when building the Todolist application.

removeEverything = async () => {
    try {
      await AsyncStorage.clear()
      alert('Storage successfully cleared!')
    } catch (e) {
      alert('Failed to clear the async storage.')
    }
  }
Enter fullscreen mode Exit fullscreen mode

This snippet will throw an alert box on the device screen when everything is cleared from storage.

Completing the App

The last two methods are going to be used to create a controlled input.

onChangeText = text => this.setState({ text })

onSubmitEditing = () => {
    const onSave = this.save
    const { text } = this.state

    if (!text) return

    onSave(text)
    this.setState({ text: '' })
}
Enter fullscreen mode Exit fullscreen mode

After that, add the code snippet for the render method, followed by the styles for each UI component. Lastly, don’t forget to export the App component so it can run on the simulator or the real device.

render() {
        const { text, name } = this.state
        return (
            <View style={styles.container}>
                <TextInput
                    style={styles.input}
                    value={text}
                    placeholder='Type your name, hit enter, and refresh'
                    onChangeText={this.onChangeText}
                    onSubmitEditing={this.onSubmitEditing}
                />
                <Text style={styles.text}>Hello {name}!</Text>
                <TouchableOpacity onPress={this.removeEverything} style={styles.button}>
                    <Text style={styles.buttonText}>Clear Storage</Text>
                </TouchableOpacity>
            </View>
        )
    }
} // class component App ends here

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center'
    },
    text: {
        fontSize: 20,
        padding: 10,
        backgroundColor: '#00ADCF'
    },
    input: {
        padding: 15,
        height: 50,
        borderBottomWidth: 1,
        borderBottomColor: '#333',
        margin: 10
    },
    button: {
        margin: 10,
        padding: 10,
        backgroundColor: '#FF851B'
    },
    buttonText: {
        fontSize: 14,
        color: '#fff'
    }
})

export default App
Enter fullscreen mode Exit fullscreen mode

Running the App

Now to run the application, go to the terminal window and execute the command expo start. After that, you’ll see the following screen on the simulator.

ss1

Since there’s no data stored right now, the text after the word Hello is empty. Use the input field to save a string or a name or anything you’d like, and then press the enter key. You’ll get the following output. Whatever input you entered, it will be displayed next to the word Hello.

ss2

Even if you refresh the Expo client, the value stored doesn’t go away. Only when pressing the button below the Hello statement that says Clear Storage will the stored value be removed.

ss3

Refresh the Expo client after you clear the storage to get the following output.

ss4

Conclusion

This completes the section about using AsyncStorage API to save and fetch the data.

If you'd like to learn more about using AsynStorage API in a real-time React Native app, learn how to build a complete Todolist app here. In this post, you are going to use Native Base UI component library.

Here is short TLDR of the Todolist post:

  • Adding navigation
  • Creating a Floating Action Button (FAB)
  • Navigating between two screens
  • Customize the header component
  • Rendering a list of items using FlatList
  • Reading data using the AsyncStorage API
  • Adding a to-do list item
  • Deleting a to-do list item
  • Mark an item check or uncheck upon completion
  • Passing data between different screens using the navigation
  • Display each to-do list item
  • Bonus section: Adding a segment

Here is a little demo of what you are going to build in the Todolist post:

ss5


I often write on Nodejs, Reactjs, and React Native. You can visit me on amanhimself.dev or you can subscribe to my weekly newsletter to receive all updates on new posts and content, straight in your inbox 💌.

Top comments (7)

Collapse
 
flexgrip472 profile image
Ray Aguilar

The 6mb limit is not accurate. It’s unlimited on iOS and configurable on android. Just thought you’d wanna know.

Collapse
 
amanhimself profile image
Aman Mittal

Thanks! What I wanted to say was that on Android it is the default size. I'll make amendments.

Collapse
 
efleurine profile image
Emmanuel • Edited

To increase the limit

// MainApplication.getPackages()
long size = 50L * 1024L * 1024L; // 50 MB
com.facebook.react.modules.storage.ReactDatabaseSupplier.getInstance(getApplicationContext()).setMaximumSize(size);
Enter fullscreen mode Exit fullscreen mode

Ref: github.com/stockulus/pouchdb-react...

Thread Thread
 
mrmovl profile image
Tomke Reibisch

Is there an upper limit to this? What if I need to store big video files?

Thread Thread
 
sshanzel profile image
Hansel Solevilla

If iOS has unlimited storage, i think it would be safe to say the same on android, i'm no expert and had no extensive experience in Android but i think to have the most reliable answer is to look at the Documentation.

Thread Thread
 
amanhimself profile image
Aman Mittal

Check the official docs for Android here: github.com/react-native-community/...

Collapse
 
shailpatel1 profile image
Shail Patel • Edited

hey @flexgrip472
you are 100 % sure ?
do you have any docs where i can confirm this ?