DEV Community

Ajmal Hasan
Ajmal Hasan

Posted on

React-Native-MMKV storage

React-Native MMKV

  • The fastest key/value storage for React Native.

  • MMKV is an efficient, small mobile key-value storage framework developed by WeChat.

  • react-native-mmkv is a library that allows you to easily use MMKV inside your React Native applications. It provides fast and direct bindings to the native C++ library which are accessible through a simple JS API.


Features

  1. Get and set strings, booleans and numbers
  2. Fully synchronous calls, no async/await, no Promises, no Bridge.
  3. Encryption support (secure storage)
  4. Multiple instances support (separate user-data with global data)
  5. Customize storage location
  6. High performance because everything is written in C++
  7. ~30x faster than AsyncStorage
  8. Uses JSI instead of the "old" Bridge
  9. iOS, Android and Web support
  10. Easy to use React Hooks API
  11. No Async/Await

Image description
Click here to compare popular storage solutions for React Native.


Installation

yarn add react-native-mmkv && cd ios && pod install
Enter fullscreen mode Exit fullscreen mode

or

npm install react-native-mmkv && cd ios && pod install
Enter fullscreen mode Exit fullscreen mode

Usage

Create a new instance

It is recommended that you re-use this instance throughout your entire app instead of creating a new instance each time, so export the storage object.

import { MMKV } from 'react-native-mmkv'
export const storage = new MMKV()
Enter fullscreen mode Exit fullscreen mode

or

import { MMKV } from 'react-native-mmkv'
export const storageEncrypted = new MMKV({
  id: `user-${userId}-storage`, //required: if when either path/encryptionKey exist
  path: `${USER_DIRECTORY}/storage`, //optional: changing storage path
  encryptionKey: 'hunter2' //optional: storing all values encrypted
})
Enter fullscreen mode Exit fullscreen mode

Click here to check how to store/retrieve values in app

Click here to see how to use it as an hook like useState

Click here to add listener when ever some key changes and you want to perform some action on that

CLick here to see how to integrate MMKV with redux-persist

Click here to use reactotron-react-native-mmkv to automatically log writes to your MMKV storage using Reactotron.


Integration of mmkv with redux persist and reactotron:

constants.js

import { MMKV } from 'react-native-mmkv'

export const storage = new MMKV(
    //     {
    //     id: `user-custom-storage`,
    //     //   path: `${USER_DIRECTORY}/storage`,
    //     encryptionKey: 'hunter2'
    // }
)

export const reduxStorageMMKV = {
    setItem: (key, value) => {
        storage.set(key, value)
        return Promise.resolve(true)
    },
    getItem: (key) => {
        const value = storage.getString(key)
        return Promise.resolve(value)
    },
    removeItem: (key) => {
        storage.delete(key)
        return Promise.resolve()
    },
}
Enter fullscreen mode Exit fullscreen mode

store.js

import { combineReducers, configureStore } from '@reduxjs/toolkit';
import cakeReducer from './slices/cakeSlice';
import icecreamReducer from './slices/icecreamSlice';
import userReducer from './slices/userSlice';
import Reactotron from './reactotronConfig/ReactotronConfig';
import {
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist';
// import AsyncStorage from '@react-native-async-storage/async-storage';
import { reduxStorageMMKV } from '../constants/constants';
// import logger from 'redux-logger';

const persistConfig = {
  key: 'root',
  version: 1,
  storage: reduxStorageMMKV, //<-- put here 
  blacklist: ['icecream', 'cake'], //these reduce will not persist data
  // whitelist: ['users'], //these reduce will persist data
};
const reducer = combineReducers({
  cake: cakeReducer,
  icecream: icecreamReducer,
  users: userReducer,
});
const persistedReducer = persistReducer(persistConfig, reducer);

//https://redux-toolkit.js.org/usage/usage-guide#use-with-redux-persist
const store = configureStore({
  reducer: persistedReducer,
  middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], //
      },
    }),
  // middleware: getDefaultMiddleware => getDefaultMiddleware().concat(logger),
  enhancers: [Reactotron.createEnhancer()],
  devTools: __DEV__,
});

export default store;
Enter fullscreen mode Exit fullscreen mode

ReactotronConfig.js

import Reactotron, { asyncStorage } from 'reactotron-react-native';
import { reactotronRedux } from 'reactotron-redux';
import mmkvPlugin from "reactotron-react-native-mmkv"
import { storage } from '../../constants/constants'

Reactotron.configure({ name: 'app_name' })
  .useReactNative()
  .use(reactotronRedux()) //  <- here i am!
  .use(mmkvPlugin({
    storage, //mmkv instance
    ignore: ["secret", "persist:root"],
    //"persist:root" key will avoid showing redux persist update everytime redux persist 
    //mmkvPlugin() accepts an object with an ignore key. The value is an array of strings you would like to prevent sending to Reactotron.
  }))
  .connect();

const yeOldeConsoleLog = console.log;
// make a new one
console.log = (...args) => {
  // always call the old one, because React Native does magic swizzling too
  yeOldeConsoleLog(...args);
  // send this off to Reactotron.
  Reactotron.display({
    name: 'CONSOLE',
    value: args,
    preview: args.length > 0 && typeof args[0] === 'string' ? args[0] : null,
  });
};

export default Reactotron;
Enter fullscreen mode Exit fullscreen mode

App.js

// /**
//  * Sample React Native App
//  * https://github.com/facebook/react-native
//  *
//  * @format
//  * @flow strict-local
//  */

import React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { persistStore } from 'redux-persist';
// import store from './redux/store';
import rtkStore from './reduxToolkit/store';
import HomeScreen from './screens/home';

let persistor = persistStore(rtkStore);

const App = () => {
  return (
    <Provider store={rtkStore}>
      <PersistGate loading={null} persistor={persistor}>
        <HomeScreen />
      </PersistGate>
    </Provider>
  );
};
export default App;
Enter fullscreen mode Exit fullscreen mode

Source Code Github Link - >

Top comments (0)