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

@byeolnaerim/global-rx-state

v0.0.2

Published

A tiny global React state primitive powered by RxJS, with named singleton stores, reducer support, and optional persistence.

Readme

@byeolnaerim/global-rx-state

A tiny global React state primitive powered by RxJS, with named singleton stores, reducer support, and optional persistence.

Install

npm install @byeolnaerim/global-rx-state rxjs react

Anonymous tuple mode

Anonymous tuple mode creates a fresh store for each call. Declare it at module top-level and export the returned functions.

// ./state
import { createRxState } from "@byeolnaerim/global-rx-state";

export const [setCount, getCount, useCount, countSubject, countReady] =
	createRxState(0);

Then import the exported functions from React components.

import { useCount } from "./state";

export function Counter() {
	const count = useCount();
	return <div>{count}</div>;
}

Do not call anonymous tuple mode inside React components or other functions. It creates a new store for each call.

function Counter() {
	// Do not do this.
	const [setCount, getCount, useCount] = createRxState(0);
	return <div>{useCount()}</div>;
}

Anonymous tuple mode does not accept storage options. It has no stable persistence key and does not generate or use hidden, random keys.

Named state mode

Named mode uses a global singleton registry keyed by name and storage options.

import { createRxState } from "@byeolnaerim/global-rx-state";

export const { setCount, getCount, useCount, countSubject, countReady } =
	createRxState(0, "count", { storage: "auto" });

If storage is omitted, the first registered storage alias for the same name is reused. If no alias exists yet, it defaults to in-memory.

To prevent confusion, it is recommended to explicitly specify the storage whenever possible.

createRxState(0, "count", { storage: "auto" });
createRxState(0, "count"); // reuses auto for count

createRxState(0, "count", { storage: "in-memory" }); // separate store

createRxState(0, "clickCount"); // defaults to 'in-memory' if no storage alias exists
createRxState(0, "clickCount", { storage: "auto" }); // separate store

Named tuple helper

Use createRxStateTuple when you want tuple ergonomics plus named singleton behavior and optional persistence.

If you already know the static name, using the named mode is generally more readable.

createRxStateTuple is particularly useful when the name is determined at runtime. For example, you can use it when you need to separate state based on a key that cannot be determined in advance—such as a workspace ID received from a server, a tab name selected by the user, or a route parameter.

import { createRxStateTuple } from "@byeolnaerim/global-rx-state";

export const [setCount, getCount, useCount, countSubject, countReady] =
	createRxStateTuple(0, "count", { storage: "auto" });

Reducer mode

Anonymous reducer tuple mode is also module-top-level only.

import { createRxReducer } from "@byeolnaerim/global-rx-state";

type CountAction = { type: "increment" } | { type: "reset" };

function countReducer(state: number, action: CountAction) {
	switch (action.type) {
		case "increment":
			return state + 1;
		case "reset":
			return 0;
		default:
			return state;
	}
}

export const [dispatchCount, getCount, useCount] = createRxReducer(
	0,
	countReducer,
);

Named reducer mode supports persistence.

export const { dispatchCount, getCount, useCount, countSubject, countReady } =
	createRxReducer(0, countReducer, "count", { storage: "auto" });

Named reducer tuple helper:

export const [dispatchCount, getCount, useCount, countSubject, countReady] =
	createRxReducerTuple(0, countReducer, "count", { storage: "auto" });

Storage

Supported storage values:

  • in-memory
  • auto
  • indexeddb
  • websql
  • localstorage
  • sessionstorage

auto uses localForage with this driver order:

IndexedDB > WebSQL > localStorage

ready is a Promise that resolves after persistent storage hydration finishes. React hooks update automatically after hydration; use ready only when code must wait for the restored value before continuing.

ESLint rule

The package includes a small ESLint rule that prevents anonymous tuple mode inside functions/components.

const globalRxState = require("@byeolnaerim/global-rx-state/eslint-rules");

module.exports = {
	plugins: {
		"global-rx-state": globalRxState,
	},
	rules: {
		"global-rx-state/no-tuple-global-rx-state-in-function": "error",
	},
};

For legacy .eslintrc setups, you can also use ESLint --rulesdir with eslint-rules/no-tuple-global-rx-state-in-function.cjs.