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

@zaatar-tech/voltix

v2.0.1

Published

Fastest React state library. Per-key subscriptions, 4 KB, zero dependencies.

Readme

⚡ Voltix

Fastest React state library.

CI npm gzip types license PRs welcome

Website · npm · GitHub · Docs · Benchmarks

Voltix is a ~4.4 KB global store for React with per-key subscriptions: set one field and only the components reading that field re-render. There is no provider to set up and there are no selector functions to write. Stores compose into a tree of nested stores and per-id lookups. Full TypeScript inference, zero dependencies, and the fastest update throughput of any React store we've measured.

import { createStore, useStoreKey } from '@zaatar-tech/voltix';

const store = createStore({ count: 0 });

function Counter() {
  const count = useStoreKey(store, 'count');
  return <button onClick={() => store.increment('count')}>{count}</button>;
}

Why Voltix

  • Surgical re-renders. Subscriptions are per key. Updating x never touches a component reading y, even when they share a store.
  • Direct values. useStoreKey(store, 'count') returns the value itself.
  • Composes into a tree. A key can hold another store or a lookup (a store per id); step into children with select(key), into lookups with at(id). Composition adds no cost to reads or writes.
  • Identity-stable state. get() returns the same object across writes, and the update path is the fastest of the group (see below).
  • Fully typed, inference-first. Keys, values, selectors, and equality functions are all inferred from your store. Selecting a key that doesn't exist is a compile error.
  • Runtime contracts. Put a zod (or valibot/arktype) schema on a key. Invalid writes are rejected, initial state included, and onSchemaError routes failures into your UI. Standard Schema keeps it dependency-free.
  • Batteries included. Action helpers, derived keys, write interceptors, persistence (sync + async), and an ESLint rule ship in the box.
  • Tiny and dependency-free. ~4.4 KB gzipped, tree-shakeable, react as the only peer.

Benchmarks

Update throughput vs the latest Zustand, Jotai, Valtio, and nanostores (vanilla store engine, ops/sec, higher is faster):

| operation | Voltix | Zustand | nanostores | Valtio | Jotai | |---|---|---|---|---|---| | update a value + notify | 43.8M | 20.1M | 18.8M | 5.3M | 2.5M | | functional update (x => x + 1) | 41.1M | 20.1M | 17.1M | 5.1M | 2.1M | | fine-grained update (1 of 1000) | 41.6M | 21.6M † | 18.7M | 56K ‡ | 2.3M | | notify 1000 subscribers | 297K | 164K | 81K | — | 53K |

Run npm run bench to reproduce (src/vs.bench.ts). The gap matters under high write rates: drag interactions, streaming data, animation, and large grids of independently updating cells.

These are store-engine numbers; in React all five re-render only the components whose data changed. On store creation and subscribe/unsubscribe Voltix is mid-pack. † Zustand's fine-grained row uses separate stores; its single-store selector pattern is O(N). ‡ Valtio batches notifications asynchronously and its per-key subscribe is O(N).

Install

npm i @zaatar-tech/voltix

The idea: fine-grained by key

You subscribe to keys. A write to a key notifies exactly the components reading it, and leaves the rest untouched.

const store = createStore({ user: { name: 'Ada' }, theme: 'dark', unread: 3 });

function Unread() {
  const unread = useStoreKey(store, 'unread'); // re-renders only when `unread` changes
  return <span>{unread}</span>;
}

store.setKey('theme', 'light'); // <Unread /> does not re-render
store.increment('unread');       // <Unread /> re-renders, nothing else does

Need several keys in one component? useStoreSelector subscribes to each and returns a slice:

const { name, theme } = useStoreSelector(store, ['user', 'theme']);

Composition: nesting and lookups

A key holding another store becomes a child, reached with select(key). createLookup(factory) makes a lookup: a store per id, created on first use. Updating one store re-renders only its readers. The factory can return a fully built store (schema, actions, onSchemaError attached) and the lookup keeps exactly that store.

const app = createStore({
  theme: 'dark',
  profile: createStore({ name: 'Ada', age: 30 }),                   // nested store
  todos: createLookup((id: string) => ({ text: '', done: false })), // lookup
});

app.setKey('theme', 'light');
app.select('profile').setKey('age', 31);
app.select('todos').at('t1').toggle('done');
app.select('todos').keys(); // ['t1']

select takes one child key, at takes one id, and they chain for depth. See Composition.

Derived state

derive computes a key from other keys in the same update; subscribers wake only when the result changes:

const store = createStore({ first: 'Ada', last: 'Lovelace', full: '' });
store.derive('full', ['first', 'last'], ({ first, last }) => `${first} ${last}`);

API at a glance

| | | |---|---| | createStore(shape, options?) | Create a store | | createLookup(factory, options?) | A map from id to store, populated lazily | | select(key) · at(id) | Step into a child · step into a lookup by id | | createActions(store, define) | Define a store's actions in one block, returned as a plain object | | options.schema | Per-key runtime contracts (zod, valibot, arktype) | | onSchemaError(handler) | React to a rejected write, with access to your actions | | useStoreKey(store, key) | Subscribe to one key, get the value directly | | useStoreSelector(store, [keys]) | Subscribe to several keys, get a slice | | createStoreHook(store) | Pre-bind a typed hook to a store | | set · setKey · update · increment · toggle | Write helpers | | mergeSet · batch · reset · derive · pick | Object updates, batching, reset, computed keys, snapshots | | subscribe · onChange · intercept | Outside-React reactions and interception | | options.equals | Per-key custom equality (compare by .id, etc.) |

Full reference in the docs.

ESLint rule

The package includes an ESLint rule (at @zaatar-tech/voltix/eslint) that flags selector keys you never use. Requires ESLint 9+ (flat config):

// eslint.config.js
import voltix from '@zaatar-tech/voltix/eslint';

export default [{
  plugins: { voltix },
  rules: { 'voltix/no-unused-selector-keys': 'warn' },
}];

Documentation

License

MIT © Ohad Baehr - Zaatar Tech