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

rozenite-zustand-devtools

v1.0.2

Published

Rozenite DevTools plugin for inspecting Zustand store state in React Native apps

Downloads

3,050

Readme

rozenite-zustand-devtools

A Rozenite DevTools plugin for inspecting Zustand store state in React Native apps.

Browse, search, and inspect all your Zustand stores in real time directly from the Rozenite DevTools panel; no middleware or store modifications required.

Features

  • Real-time state inspection: See live updates as your Zustand stores change
  • Table & JSON views: Toggle between a structured key-value table and raw JSON
  • Collapsible nested objects: Expand/collapse objects and arrays in table view
  • Color-coded values: Strings (green), numbers (blue), booleans (purple), null/undefined (gray)
  • Store filtering: Quickly find stores by name when you have many registered
  • Copy to clipboard: One-click copy of any store's state as formatted JSON
  • Last updated timestamps: See when each store was last modified
  • Auto-select on load: First store is selected automatically when the panel opens
  • Zero store modifications: Works with any Zustand store out of the box via getState() and subscribe()
  • Debounced updates: Uses requestAnimationFrame to batch rapid state changes and avoid flooding the bridge
  • Production-safe: The hook is replaced with a no-op in production builds, so no devtools code ships to users

Prerequisites

  • Rozenite integrated in your React Native project
  • Zustand for state management

Installation

npm install -D rozenite-zustand-devtools

Setup

1. Define your stores

Create a file to list the Zustand stores you want to inspect (e.g., services/zustand/devtools.ts):

import type { StoreEntry } from 'rozenite-zustand-devtools';
import { useMyStore } from './myStore';
import { useAuthStore } from './authStore';

export const zustandStores: StoreEntry[] = [
  { name: 'myStore', store: useMyStore },
  { name: 'auth', store: useAuthStore },
];

2. Call the hook in your root component

Add useZustandDevTools in your root layout or App.tsx, alongside your other Rozenite hooks:

import { useZustandDevTools } from 'rozenite-zustand-devtools';
import { zustandStores } from './services/zustand/devtools';

export default function Layout() {
  // Safe to call unconditionally - no-ops in production
  useZustandDevTools(zustandStores);

  return <>{/* ... */}</>;
}

3. Start with Rozenite enabled

WITH_ROZENITE=true npx expo start -c

Open the Rozenite DevTools and you'll see a Zustand tab with all your registered stores.

How It Works

The plugin has two parts that communicate over Rozenite's WebSocket bridge:

React Native side (runs in your app)

The useZustandDevTools hook:

  1. Connects to the Rozenite DevTools host via useRozeniteDevToolsClient from @rozenite/plugin-bridge
  2. Sends an initial snapshot of all stores on mount
  3. Subscribes to each Zustand store using the standard .subscribe() API
  4. On any state change, serializes the store state (excluding functions) and sends it to the DevTools panel
  5. Responds to snapshot requests from the panel with the full state of all stores
  6. Debounces updates using requestAnimationFrame to prevent bridge flooding during rapid state changes
  7. Cleans up all subscriptions on unmount

DevTools panel (runs in the browser)

The panel renders inside the Rozenite DevTools as an iframe and:

  1. Requests a full snapshot of all stores on mount
  2. Listens for incremental store-update events as state changes
  3. Displays stores in a two-column layout: store list on the left, state inspector on the right
  4. Supports both Table view (structured key-value with collapsible nesting) and JSON view (raw formatted JSON)

Communication events

| Event | Direction | Description | |-------|-----------|-------------| | zustand:request-snapshot | Panel -> App | Panel requests current state of all stores | | zustand:snapshot | App -> Panel | Full state snapshot of all registered stores | | zustand:store-update | App -> Panel | Incremental update for a single store |

API

useZustandDevTools(stores: StoreEntry[])

React hook that connects to the Rozenite DevTools and sends live Zustand state updates. Safe to call unconditionally - in production, the hook is replaced with a no-op at the entry-point level, so no devtools code is bundled.

  • stores: Array of stores to register
type StoreEntry = {
  name: string;
  store: {
    getState: () => object;
    subscribe: (listener: () => void) => () => void;
  };
};

Any Zustand store created with create() satisfies the store interface, no wrappers needed. The name is what appears in the DevTools sidebar.

Compatibility

| Dependency | Version | |------------|---------| | Rozenite | >= 1.3.0 | | Zustand | Any version (uses standard getState/subscribe API) | | React Native | >= 0.70 | | React | >= 18 |

License

MIT