How to cache and fetch data in React Native

Caching means storing data for later usage. Caching data has many benefits when it comes to mobile-based applications, such as React Native:

  • Caching improves user experience since users don’t have to wait for data to be fetched repeatedly. Once data is cached, it can be fetched instantaneously each time.

  • Caching data reduces the load on back-end servers and databases. Consequently, we can optimize our resources and utilize them more efficiently.

  • Caching data helps achieve cost optimizations. Storing or fetching data via a remote API, server, or database can incur charges that pile up over time. Caching prevents this since storing and fetching from a cache requires significantly lesser resources and time as compared to a remote API, server, or database.

We can cache and fetch data in React Native using the async storage system, which is an unencrypted, asynchronous, persistent, key-value storage system that helps store data in the form of a string format.

To use the async storage system, we have to import AsyncStorage from @react-native-async-storage/async-storage. The AsyncStorage provides us with setItem and getItem methods that can be used to cache and fetch data, respectively.

Syntax

The setItem method of AsyncStorage has the following syntax:

AsyncStorage.setItem(key, value);
Syntax for the setItem method of AsyncStorage

The getItem method of AsyncStorage has the following syntax:

AsyncStorage.getItem(key);
Syntax for the getItem method of AsyncStorage

Parameters

The setItem method takes the following parameters:

  • key: This is the key of the data to be cached.

  • value: This is the value of the data to be cached.

The getItem method takes the following parameter:

  • key: This is the key of the data to be fetched from the cache.

Code example

Let’s look at an example where we utilize the setItem and getItem methods of the AsyncStorage to cache and fetch data, respectively.

/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * <p>This source code is licensed under the MIT license found in the LICENSE file in the root
 * directory of this source tree.
 */
package com.reactnativelearning;

import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceEventListener;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;

/**
 * Class responsible of loading Flipper inside your React Native application. This is the debug
 * flavor of it. Here you can add your own plugins and customize the Flipper setup.
 */
public class ReactNativeFlipper {
  public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
    if (FlipperUtils.shouldEnableFlipper(context)) {
      final FlipperClient client = AndroidFlipperClient.getInstance(context);

      client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
      client.addPlugin(new DatabasesFlipperPlugin(context));
      client.addPlugin(new SharedPreferencesFlipperPlugin(context));
      client.addPlugin(CrashReporterPlugin.getInstance());

      NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
      NetworkingModule.setCustomClientBuilder(
          new NetworkingModule.CustomClientBuilder() {
            @Override
            public void apply(OkHttpClient.Builder builder) {
              builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
            }
          });
      client.addPlugin(networkFlipperPlugin);
      client.start();

      // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
      // Hence we run if after all native modules have been initialized
      ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
      if (reactContext == null) {
        reactInstanceManager.addReactInstanceEventListener(
            new ReactInstanceEventListener() {
              @Override
              public void onReactContextInitialized(ReactContext reactContext) {
                reactInstanceManager.removeReactInstanceEventListener(this);
                reactContext.runOnNativeModulesQueueThread(
                    new Runnable() {
                      @Override
                      public void run() {
                        client.addPlugin(new FrescoFlipperPlugin());
                      }
                    });
              }
            });
      } else {
        client.addPlugin(new FrescoFlipperPlugin());
      }
    }
  }
}
Caching and fetching data using the async storage system

Code explanation

  • Line 1: We import React and the useState Hook from the react library.

  • Lines 2–9: We import the required components from the react-native library.

  • Line 10: We import AsyncStorage from @react-native-async-storage/async-storage.

  • Line 14: We use the useState Hook to initialize the state variable key. We set the initial state as empty.

  • Line 15: We use the useState Hook to initialize the state variable value. We set the initial state as empty.

  • Lines 17–32: We define the function cacheData to cache the data. If the values for key and value are empty, an error will be shown using the Alert box, and the function will return. Otherwise, we use the setItem method of the AsyncStorage to cache data according to the values of key and value provided. Once successfully cached, a success message is shown using the Alert box. If there is any error while caching data, an error will be shown using the Alert box. Relevant error details are then logged using the console.log method.

  • Lines 34–51: We define the function fetchData to fetch the data. If the value for key is empty, an error will be shown using the Alert box, and the function will return. Otherwise, we use the getItem method of the AsyncStorage to fetch data according to the value of the key provided. If the value returned by the getItem method is null, it means that data corresponding to the provided key value does not exist in the cache and vice versa. We show success or failure messages accordingly for both scenarios using the Alert box. Furthermore, an error will be shown using the Alert box if there is any error while fetching data. Relevant error details are then logged using the console.log method.

  • Lines 54–75: We write the logic for the user interface of the React Native application.

  • Lines 79–99: We define the styles for our user interface.

Note: You can download and execute the code example above on your local system or machine. Follow the official documentation to set up the development environment. Furthermore, note that the code example above is for the Android operating system.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved