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

statekit-react

v1.0.6

Published

Typed, reactive state adapter over Redux Toolkit with nested .get(), .set(), .use() and plugin system

Readme

state-kit

💡 StateKit is a convenient state management tool built on top of Redux Toolkit.
It provides a simple, reactive API for accessing deeply nested state using .get(), .set(), and .use()
as if you're working with a plain object, but with full reactivity, type safety, and plugin support.


✨ In short:

  • You write state.user.profile.name.set(...) — and the state updates
  • You call state.user.profile.name.use() — and the component automatically subscribes to changes
  • Under the hood, it's powered by Redux + Immer + React — but you never deal with the complexity yourself

🚀 Features

  • 🔁 .get(), .set(), .use() and .useWatch() on any nested path
  • ⚛️ Fully typed reactive access
  • 📦 Redux DevTools compatible
  • 🔌 Plugin system: persist, logger, custom
  • 🧩 Modular, scalable, predictable

📦 Full install (if you're starting from scratch)

npm install statekit-react react react-dom react-redux @reduxjs/toolkit

📦 Installation (if you already use React and Redux Toolkit)

If your project already uses react, @reduxjs/toolkit, and react-redux,
you can simply install state-kit as a lightweight, plugin-ready state manager:

# Using npm
npm install statekit-react

# Using yarn
yarn add statekit-react

# Using pnpm
pnpm add statekit-react

🧪 Usage

import React from 'react';
import { Provider } from 'react-redux';
import { createState, store, useLocalStorage } from 'statekit-react';

// create slice state
const counter = createState('counter', { value: 0 });

// Pure watcher (not bound to any DOM)
function Logger() {
    counter.value.useWatch((v) => {
        console.log('[useWatch] value changed:', v)
    });

    return null;
}

// UI component that reacts to changes
function Display() {
    const value = counter.value.use();
    return <div>Value: {value}</div>;   // or even easier: <div>Value: {counter.value.use()}</div>
}

// Updates state every second
function Updater() {
    React.useEffect(() => {
        const i = setInterval(() => {
            counter.value.set(v => v + 1);
        }, 1000);
        return () => clearInterval(i);
    }, []);
    return null;
}

// Root component
export function App() {
    return (
        <Provider store={store}>
            <Logger />
            <Updater />
            <Display />
        </Provider>
    );
}

🧮 .set() usage examples

🔢 For primitive values (e.g. number, string, boolean)

You must return the new value:

// create
const editor = createState('editor', {
    size: { width: 100, height: 200 },
});

// primitive: number
editor.size.width.set((prevWidth) => prevWidth + 1);

🧱 For objects or arrays

You can mutate the draft directly:

// create
const editor = createState('editor', {
    size: { width: 100, height: 200 },
});

editor.size.set((prevSize) => {
    prevSize.width += 1;
    prevSize.height += 10;

    // optional: can return draft, but not required
    return prevSize;
});

⚡️ Dynamic nested field creation

StateKit allows you to mutate and create fields on the fly — even if they were not part of the initial state.

You can start with an empty object:

const counter = createState('counter', {}); // no initial shape

And safely assign new fields during .set(...):

counter.set((state) => {
    if (!state.count) state.count = 0;
    state.count++;
});

Use .use() or .useWatch() as usual:

function Display() {
    return <div>{counter.use()?.count}</div>;
}

function Logger() {
    counter.useWatch((state) => {
        console.log('updated:', state);
    });
    return null;
}

✅ Works reactively — no need to predefine structure.

PLUGINS

💾 Persist local storage plugin

import { createState, useLocalStorage } from 'statekit-react';

// 👇 Creates reactive state with auto-persist
const editor = createState('editor', {
    layout: [],
    size: { width: 100, height: 200 },
}, [
    useLocalStorage({ restore: true }) // ✅ auto-restore from localStorage
]);

🙋‍♂️ Feedback / Contributions

Feel free to open issues or submit PRs if you have suggestions or improvements!