
Research
/Security News
Mini Shai-Hulud Campaign Hits Red Hat Cloud Services npm Packages
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.
@dvashim/store
Advanced tools
A minimal, lightweight React state management library built on useSyncExternalStore.
npm:
npm install @dvashim/store
or pnpm:
pnpm add @dvashim/store
Peer dependencies: react and react-dom ^18.0.0 || ^19.0.0
import { createStore, useStore } from '@dvashim/store'
const count$ = createStore(0)
function Counter() {
const count = useStore(count$)
return (
<button onClick={() => count$.update((n) => n + 1)}>
Count: {count}
</button>
)
}
createStore(initialState?)Creates a new Store instance.
const count$ = createStore(0)
const user$ = createStore({ name: 'Alice', age: 30 })
// Without initial state — type defaults to T | undefined
const data$ = createStore<string>()
StoreReactive state container with subscription-based change notification.
store.get()Returns the current state.
const count$ = createStore(10)
count$.get() // 10
store.set(state, options?)Replaces the state. Skipped if the value is identical (Object.is), unless { force: true } is passed.
count$.set(5)
// Force notify subscribers even if the value hasn't changed
count$.set(5, { force: true })
store.update(updater, options?)Derives the next state via an updater function. Calling set() or update() from within a subscriber throws an error.
count$.update((n) => n + 1)
// With objects — always return a new reference
const todos$ = createStore([{ text: 'Buy milk', done: false }])
todos$.update((todos) => [...todos, { text: 'Walk dog', done: false }])
store.subscribe(fn)Registers a callback invoked on each state change with the new and previous state. Returns an unsubscribe function.
const unsubscribe = count$.subscribe((state, prevState) => {
console.log(`Count changed from ${prevState} to ${state}`)
})
// Later...
unsubscribe()
ComputedStoreA read-only reactive store that derives its value from a source store using a selector. Automatically updates when the source changes. Accepts any SourceStore<T> (including Store or another ComputedStore) as its source.
import { createStore, ComputedStore } from '@dvashim/store'
const todos$ = createStore([
{ text: 'Buy milk', done: true },
{ text: 'Walk dog', done: false },
])
const remaining$ = new ComputedStore(todos$, (todos) =>
todos.filter((t) => !t.done).length
)
remaining$.get() // 1
remaining$.subscribe((count, prev) => console.log(`${prev} → ${count}`))
ComputedStore implements SourceStore<U>, so it can be used as the source for another ComputedStore.
const count$ = new ComputedStore(todos$, (todos) => todos.length)
const label$ = new ComputedStore(count$, (n) => `${n} items`)
label$.get() // "2 items"
computed.connect() / computed.disconnect()Control the subscription to the source store. After disconnect(), the derived value stops updating and get() returns the last known value. Call connect() to resume — it immediately syncs the derived value with the current source state before resubscribing.
remaining$.disconnect()
remaining$.isConnected // false
remaining$.connect()
remaining$.isConnected // true
useStore(store, selector?)React hook that subscribes a component to any SourceStore — works with both Store and ComputedStore.
function Counter() {
const count = useStore(count$)
return <p>{count}</p>
}
function Remaining() {
const remaining = useStore(remaining$)
return <p>{remaining} left</p>
}
Derive a value from the store state. The selector should return a referentially stable value (primitive or existing object reference) to avoid unnecessary re-renders.
const user$ = createStore({ name: 'Alice', age: 30 })
function UserName() {
const name = useStore(user$, (user) => user.name)
return <p>{name}</p>
}
The following types are exported from the package:
import type { Selector, Subscriber } from '@dvashim/store'
| Type | Definition |
|---|---|
Selector<T, U> | (state: T) => U |
Subscriber<T> | (state: T, prevState: T) => void |
Define stores outside of components and import them where needed.
// stores/auth.ts
import { createStore } from '@dvashim/store'
export const token$ = createStore<string | null>(null)
export function login(token: string) {
token$.set(token)
}
export function logout() {
token$.set(null)
}
// components/Profile.tsx
import { useStore } from '@dvashim/store'
import { token$, logout } from '../stores/auth'
function Profile() {
const token = useStore(token$)
if (!token) return <p>Not logged in</p>
return <button onClick={logout}>Log out</button>
}
import { createStore, useStore } from '@dvashim/store'
const firstName$ = createStore('Alice')
const lastName$ = createStore('Smith')
function FullName() {
const firstName = useStore(firstName$)
const lastName = useStore(lastName$)
return <p>{firstName} {lastName}</p>
}
import { Store } from '@dvashim/store'
class TimerService {
readonly seconds$ = new Store(0)
#interval: ReturnType<typeof setInterval> | undefined
start() {
this.#interval = setInterval(() => {
this.seconds$.update((s) => s + 1)
}, 1000)
}
stop() {
clearInterval(this.#interval)
}
}
MIT
FAQs
Yet another state management in React
We found that @dvashim/store demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.

Security News
The Rust project is moving toward formal rules on LLM use in contributions after months of internal debate over maintainer burden, code quality, and contributor experience.