tanstack-store
Skill3 starsChanged 2 months agoApache-2.0View on GitHub
Framework-agnostic, immutable reactive data store with framework adapters for React, Vue, Solid, Angular, and Svelte.
- Installs packages
1 other project uses a version of this.
Adopted by
Most recently taken up by
- Firzus/agent-skillstheir own version, first seen Oct 23, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- Firzus/agent-skills★ 4same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository28 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .agents/skills/vercel-composition-patterns/AGENTS.mdAGENTS.md
- .agents/skills/vercel-react-best-practices/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- argos-data-importSkill
- argos-releaseSkill
- argos-sddSkill
- awwwards-animationsSkill
- baseline-uiSkill
- bun-file-ioSkill
- design-taste-frontendSkill
- fork-syncSkill
- pi-updateSkill
- react-doctorSkill
- shadcnSkill
- tanstack-formSkill
- tanstack-pacerSkill
- tanstack-querySkill
- tanstack-rangerSkill
- tanstack-routerSkill
- tanstack-tableSkill
- tanstack-virtualSkill
- turborepoSkill
- vercel-composition-patternsSkill
- vercel-react-best-practicesSkill
- vgpuSkill
- viteSkill
- web-design-guidelinesSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 289
Use
shallow: when selectors return objects/arrays - Very specific: line 292
Never mutate state directly: - always use setState
- Distinctive: line 296
Select primitives: when possible (no equality fn needed)
- Distinctive: line 301
Not cleaning up subscriptions/unmount functions (memory leaks)
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Overview
TanStack Store is a lightweight reactive store (signals-like) that powers the internals of TanStack libraries. It provides Store for state, Derived for computed values, Effect for side effects, and batch for atomic updates. Framework adapters provide reactive hooks.
Core: @tanstack/store
React: @tanstack/react-store
Installation
npm install @tanstack/store @tanstack/react-storeStore
Creating a Store
import { Store } from '@tanstack/store'
const countStore = new Store(0)
const userStore = new Store<{ name: string; email: string }>({
name: 'Alice',
email: 'alice@example.com',
})Updating State
// Function updater (immutable update)
countStore.setState((prev) => prev + 1)
userStore.setState((prev) => ({ ...prev, name: 'Bob' }))Subscribing to Changes
const unsub = countStore.subscribe(() => {
console.log('Count:', countStore.state)
})
// Cleanup
unsub()Store Options
const store = new Store(initialState, {
// Custom update function
updateFn: (prevValue) => (updater) => {
return updater(prevValue) // custom logic
},
// Callback on subscribe
onSubscribe: (listener, store) => {
console.log('New subscriber')
return () => console.log('Unsubscribed')
},
// Callback on every update
onUpdate: () => {
console.log('State updated:', store.state)
},
})Store Properties
store.state // Current state
store.prevState // Previous state
store.listeners // Set of listener callbacksDerived (Computed Values)
import { Store, Derived } from '@tanstack/store'
const count = new Store(5)
const multiplier = new Store(2)
const doubled = new Derived({
deps: [count, multiplier],
fn: ({ currDepVals }) => currDepVals[0] * currDepVals[1],
})
// MUST mount to activate
const unmount = doubled.mount()
console.log(doubled.state) // 10
count.setState(() => 10)
console.log(doubled.state) // 20
// Cleanup
unmount()Derived with Previous Value
const accumulated = new Derived({
deps: [count],
fn: ({ prevVal, currDepVals }) => {
return currDepVals[0] + (prevVal ?? 0)
},
})Chaining Derived
const filtered = new Derived({
deps: [dataStore, filterStore],
fn: ({ currDepVals }) => currDepVals[0].filter(matchesFilter(currDepVals[1])),
})
const sorted = new Derived({
deps: [filtered, sortStore],
fn: ({ currDepVals }) => [...currDepVals[0]].sort(comparator(currDepVals[1])),
})
const paginated = new Derived({
deps: [sorted, pageStore],
fn: ({ currDepVals }) => currDepVals[0].slice(
currDepVals[1].offset,
currDepVals[1].offset + currDepVals[1].limit,
),
})Effect (Side Effects)
import { Store, Effect } from '@tanstack/store'
const count = new Store(0)
const logger = new Effect({
deps: [count],
fn: () => {
console.log('Count changed:', count.state)
// Optionally return cleanup function
return () => console.log('Cleaning up')
},
eager: false, // true = run immediately on mount
})
const unmount = logger.mount()
count.setState(() => 1) // logs: "Count changed: 1"
unmount()Effect with Cleanup
const timerEffect = new Effect({
deps: [intervalStore],
fn: () => {
const id = setInterval(() => { /* ... */ }, intervalStore.state)
return () => clearInterval(id) // cleanup on next run or unmount
},
})Batch
Group multiple updates into one notification:
import { batch } from '@tanstack/store'
// Subscribers fire only once with final state
batch(() => {
countStore.setState(() => 1)
nameStore.setState(() => 'Alice')
settingsStore.setState((prev) => ({ ...prev, theme: 'dark' }))
})React Integration
useStore Hook
import { useStore } from '@tanstack/react-store'
// Subscribe to full state
function Counter() {
const count = useStore(countStore)
return <button onClick={() => countStore.setState((c) => c + 1)}>{count}</button>
}
// Subscribe with selector (performance optimization)
function UserName() {
const name = useStore(userStore, (state) => state.name)
return <span>{name}</span>
}
// Subscribe to Derived
function DoubledDisplay() {
const value = useStore(doubledDerived)
return <span>{value}</span>
}shallow Equality Function
Prevents re-renders when selector returns structurally-equal objects:
import { useStore } from '@tanstack/react-store'
import { shallow } from '@tanstack/react-store'
function TodoList() {
// Without shallow: re-renders on ANY state change (new object ref)
// With shallow: only re-renders when items actually change
const items = useStore(todosStore, (state) => state.items, shallow)
return <ul>{items.map(/* ... */)}</ul>
}Mounting Derived/Effect in React
function MyComponent() {
useEffect(() => {
const unmountDerived = myDerived.mount()
const unmountEffect = myEffect.mount()
return () => {
unmountDerived()
unmountEffect()
}
}, [])
const value = useStore(myDerived)
return <span>{value}</span>
}Module-Level Store Pattern
// stores/counter.ts
import { Store, Derived } from '@tanstack/store'
export const counterStore = new Store(0)
export const doubledCount = new Derived({
deps: [counterStore],
fn: ({ currDepVals }) => currDepVals[0] * 2,
})
// Actions as plain functions
export function increment() {
counterStore.setState((c) => c + 1)
}
export function reset() {
counterStore.setState(() => 0)
}Framework Adapters
| Framework | Package | Hook/Composable |
| React | @tanstack/react-store | useStore(store, selector?, equalityFn?) |
| Vue | @tanstack/vue-store | useStore(store, selector?) (returns computed ref) |
| Solid | @tanstack/solid-store | useStore(store, selector?) (returns signal) |
| Angular | @tanstack/angular-store | injectStore(store, selector?) (returns signal) |
| Svelte | @tanstack/svelte-store | useStore(store, selector?) (returns $state) |
Best Practices
- Define stores at module level - they're singletons
- Use selectors in
useStoreto prevent unnecessary re-renders - Use
shallowwhen selectors return objects/arrays - Always call
mount()on Derived and Effect instances - Always clean up unmount functions (especially in React useEffect)
- Never mutate state directly - always use
setState - Use
batchfor multiple related updates - Use Derived chains for data transformations (filter -> sort -> paginate)
- Return cleanup functions from Effect
fnfor timers/listeners - Select primitives when possible (no equality fn needed)
Common Pitfalls
- Forgetting to
mount()Derived/Effect (they won't activate) - Not cleaning up subscriptions/unmount functions (memory leaks)
- Mutating
store.statedirectly instead of usingsetState - Creating new object references in selectors without
shallow - Using
useStorewithout a selector (subscribes to everything) - Forgetting
eager: truewhen Effect should run immediately
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

