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.
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);
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.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()); } } } }
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