npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

reactotron-plugin-mmkv

v1.0.1

Published

Full-featured Reactotron plugin for react-native-mmkv — operation logging + State tab integration

Readme

reactotron-plugin-mmkv

A full-featured Reactotron plugin for react-native-mmkv that provides:

  • 🔍 Timeline Logging — Log every MMKV operation (SET, UPDATE, GET, DELETE, CLEAR_ALL) with old/new value diffs
  • 📊 State Tab Integration — Browse all MMKV key-values in Reactotron's State tab, just like Redux state
  • 🔄 Live Subscriptions — Watch MMKV values update in real-time in the State tab
  • 🎯 Operation Differentiation — Distinguishes between SET (new key) and UPDATE (existing key)
  • 🔇 Configurable Noise Control — Ignore specific keys, toggle read/contains logging

Why?

The existing reactotron-react-native-mmkv package only uses MMKV's addOnValueChangedListener, which:

  • ❌ Only fires on value changes (not on get/delete/clearAll)
  • ❌ Only provides the key — no operation type, no old/new values
  • ❌ Shows everything as Set "key" — useless for debugging
  • ❌ No State tab support

This plugin fixes all of these by using a Proxy-based interception approach.

Installation

npm install reactotron-plugin-mmkv
# or
yarn add reactotron-plugin-mmkv

Peer Dependencies

Make sure you have these installed:

  • react-native >= 0.74.0 (requires New Architecture)
  • react-native-mmkv >= 3.0.0
  • reactotron-core-client >= 2.0.0 (comes with reactotron-react-native)

Usage

Basic Setup

import Reactotron from 'reactotron-react-native';
import { mmkvPlugin } from 'reactotron-plugin-mmkv';
import { MMKV } from 'react-native-mmkv';

// 1. Create your raw MMKV instance
const rawStorage = new MMKV({ id: 'mmkv.default' });

// 2. Create the plugin — returns the Reactotron plugin + proxied storage
const { plugin, storage } = mmkvPlugin({ storage: rawStorage });

// 3. Wire up Reactotron
Reactotron
  .configure()
  .useReactNative()
  .use(plugin)
  .connect();

// 4. Use `storage` everywhere in your app (NOT rawStorage)
export { storage as LocalStorage };

With Redux

import Reactotron from 'reactotron-react-native';
import { reactotronRedux } from 'reactotron-redux';
import { mmkvPlugin } from 'reactotron-plugin-mmkv';
import { MMKV } from 'react-native-mmkv';

const rawStorage = new MMKV();
const { plugin, storage } = mmkvPlugin({
  storage: rawStorage,
  ignore: ['noisy_key'],
});

Reactotron
  .configure()
  .useReactNative()
  .use(reactotronRedux())
  .use(plugin)
  .connect();

export { storage as LocalStorage };

What You'll See in Reactotron

Timeline Tab

Every MMKV operation appears as a log entry with clear visual indicators:

🟢 MMKV SET      "user_token"    →  "eyJhbGci..."
🔵 MMKV GET      "user_token"    →  "eyJhbGci..."
🟡 MMKV UPDATE   "theme"         →  "dark" (was "light")
🔴 MMKV DELETE   "session_id"    (was "abc123")
⚫ MMKV CLEAR_ALL                 removed 5 key(s)

State Tab

Browse MMKV data alongside Redux state:

├── auth          (Redux)
├── user          (Redux)
├── settings      (Redux)
└── mmkv          ← MMKV data
    ├── user_token: "eyJhbGci..."
    ├── theme: "dark"
    ├── user_settings: { volume: 80, muted: false }
    └── onboarding_complete: true

JSON-stored objects are automatically parsed and browsable — you can drill into nested structures.

Configuration

const { plugin, storage } = mmkvPlugin({
  // Required: your MMKV instance
  storage: rawStorage,

  // Optional: keys to never log (default: [])
  ignore: ['noisy_analytics_key', 'frequent_cache_key'],

  // Optional: log GET operations in timeline (default: false)
  // ⚠️ Can be very noisy — enable only when debugging specific reads
  logReads: false,

  // Optional: log CONTAINS operations in timeline (default: false)
  logContains: false,

  // Optional: namespace in State tab (default: 'mmkv')
  // Change this if you have multiple MMKV instances
  stateNamespace: 'mmkv',
});

API

mmkvPlugin(config)

Creates the plugin and proxied storage.

Parameters:

| Option | Type | Default | Description | |--------|------|---------|-------------| | storage | MMKV | required | Your MMKV instance | | ignore | string[] | [] | Keys to exclude from logging | | logReads | boolean | false | Log GET operations | | logContains | boolean | false | Log CONTAINS operations | | stateNamespace | string | 'mmkv' | State tab namespace |

Returns:

| Property | Type | Description | |----------|------|-------------| | plugin | Function | Pass to Reactotron.use(plugin) | | storage | MMKV | Proxied MMKV instance for your app |

Reactotron Features

After connecting, these methods are available on the Reactotron instance:

  • Reactotron.mmkvGetState() — Returns all MMKV data as an object
  • Reactotron.mmkvGetKeys() — Returns all MMKV keys

Multiple MMKV Instances

If you use multiple MMKV instances, create a plugin for each with a different namespace:

const userStorage = new MMKV({ id: 'user' });
const cacheStorage = new MMKV({ id: 'cache' });

const userPlugin = mmkvPlugin({
  storage: userStorage,
  stateNamespace: 'mmkv.user',
});

const cachePlugin = mmkvPlugin({
  storage: cacheStorage,
  stateNamespace: 'mmkv.cache',
});

Reactotron
  .use(userPlugin.plugin)
  .use(cachePlugin.plugin)
  .connect();

How It Works

  1. Proxy Interception: Your MMKV instance is wrapped in a JS Proxy. Every method call (set, getString, delete, etc.) is intercepted, logged to Reactotron, and then forwarded to the real MMKV instance.

  2. State Tab Protocol: The plugin responds to Reactotron's state commands (state.keys.request, state.values.request, state.values.subscribe) to make MMKV data browsable in the State tab.

  3. Zero Production Overhead: The proxy only logs when Reactotron is connected. In production (where Reactotron isn't configured), there is no performance impact.

Contributing

# Clone the repo
git clone https://github.com/mdRehan991/reactotron-plugin-mmkv.git

# Install dependencies
npm install

# Run tests
npm test

# Build
npm run build

License

MIT