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);
The getItem method of AsyncStorage has the following syntax:
AsyncStorage.getItem(key);
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());
}
}
}
}
Code explanation
-
Line 1: We import
Reactand theuseStateHook from thereactlibrary. -
Lines 2–9: We import the required components from the
react-nativelibrary. -
Line 10: We import
AsyncStoragefrom@react-native-async-storage/async-storage. -
Line 14: We use the
useStateHook to initialize the state variablekey. We set the initial state as empty. -
Line 15: We use the
useStateHook to initialize the state variablevalue. We set the initial state as empty. -
Lines 17–32: We define the function
cacheDatato cache the data. If the values forkeyandvalueare empty, an error will be shown using theAlertbox, and the function will return. Otherwise, we use thesetItemmethod of theAsyncStorageto cache data according to the values ofkeyandvalueprovided. Once successfully cached, a success message is shown using theAlertbox. If there is any error while caching data, an error will be shown using theAlertbox. Relevant error details are then logged using theconsole.logmethod. -
Lines 34–51: We define the function
fetchDatato fetch the data. If the value forkeyis empty, an error will be shown using theAlertbox, and the function will return. Otherwise, we use thegetItemmethod of theAsyncStorageto fetch data according to the value of thekeyprovided. If the value returned by thegetItemmethod isnull, it means that data corresponding to the providedkeyvalue does not exist in the cache and vice versa. We show success or failure messages accordingly for both scenarios using theAlertbox. Furthermore, an error will be shown using theAlertbox if there is any error while fetching data. Relevant error details are then logged using theconsole.logmethod. -
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