How to use Realm with Redux Persist for caching data in React Native?

Steve Blue
3 min readJul 16, 2023

--

Realm provides a fast and efficient local database solution that can be used for data persistence and caching. Realm’s features make it well-suited for caching data in React Native applications:

1. Performance: Realm is known for its fast performance. It uses a compact and efficient binary storage format, which allows for quick read and write operations.

2. Offline-First: Realm’s database operates offline, allowing your application to continue functioning even when there is no network connection. You can fetch data from the Realm cache instead of making API calls, providing a seamless user experience.

3. Query Capabilities: Realm supports advanced querying capabilities, including filtering, sorting, and indexing. This allows you to easily retrieve and manipulate cached data based on specific criteria.

4. Data Synchronization: Realm offers data synchronization features that enable you to synchronize data between the local Realm database and a server-side database. This can be useful for keeping the cache up-to-date with the latest data from the server.

5. Cross-Platform Compatibility: Realm is compatible with both iOS and Android platforms, making it a reliable choice for caching data in React Native applications.

By utilizing Realm as a cache storage solution, you can improve the performance and responsiveness of your application by reducing the need for frequent API calls and leveraging the power of a local database.

  1. Install the necessary packages:
npm install realm
npm install @reduxjs/toolkit
npm install redux-saga
npm install redux-persist

2. Set up Redux Toolkit and Redux Persist with Realm:

// store.js
import { configureStore } from '@reduxjs/toolkit';
import createSagaMiddleware from 'redux-saga';
import { persistStore, persistReducer } from 'redux-persist';
import { combineReducers } from 'redux';
import Realm from 'realm';

import rootSaga from './sagas';
import rootReducer from './reducers';

const sagaMiddleware = createSagaMiddleware();

// Define your Realm schema
const DataSchema = {
name: 'Data',
properties: {
id: 'int',
name: 'string',
// Define other properties
},
};

// Create a custom storage engine for Redux Persist using Realm
const realm = new Realm({ schema: [DataSchema] });

const realmStorage = {
getItem: (key, callback) => {
const item = realm.objects('Data').filtered(`id = ${key}`)[0];
callback(null, item ? JSON.stringify(item) : null);
},
setItem: (key, value, callback) => {
realm.write(() => {
const data = JSON.parse(value);
realm.create('Data', data, true);
});
callback(null);
},
removeItem: (key, callback) => {
realm.write(() => {
const item = realm.objects('Data').filtered(`id = ${key}`)[0];
realm.delete(item);
});
callback(null);
},
};

// Configure Redux Persist with the custom storage engine
const persistConfig = {
key: 'root',
storage: realmStorage,
};

// Combine reducers
const combinedReducers = combineReducers({
root: rootReducer,
});

const persistedReducer = persistReducer(persistConfig, combinedReducers);

const store = configureStore({
reducer: persistedReducer,
middleware: [sagaMiddleware],
});

const persistor = persistStore(store);

sagaMiddleware.run(rootSaga);

export { store, persistor };

3. Update your main component:

import React, { useEffect } from 'react';
import { ActivityIndicator, Text, View } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';

import { fetchData } from './reducers';
import { persistor, store } from './store';

const App = () => {
const dispatch = useDispatch();
const { data, loading, error } = useSelector((state) => state.root);

useEffect(() => {
// Dispatch the fetchData action when the component mounts
dispatch(fetchData());
}, []);

if (loading) {
return <ActivityIndicator size="large" />;
}

if (error) {
return <Text>Error: {error}</Text>;
}

return (
<PersistGate loading={null} persistor={persistor}>
<View>
{data && data.map((item) => <Text key={item.id}>{item.name}</Text>)}
</View>
</PersistGate>
);
};

export default App;

By using Realm as the storage engine for Redux Persist, the Redux state, including the cached data, will be persisted and rehydrated using Realm. The custom storage engine interacts with Realm to store, retrieve, and remove the Redux state.

--

--

Steve Blue

Experienced Mobile Application Developer with a demonstrated history of working in the computer software industry.