From 81a96dca297fce29669c145fcca122e373924fe0 Mon Sep 17 00:00:00 2001 From: a067334 Date: Fri, 1 May 2026 14:34:08 -0500 Subject: [PATCH] refactor: rename `useStore` to `useClassyStore` --- .changeset/petite-wombats-count.md | 5 ++ CLAUDE.md | 14 ++-- README.md | 4 +- .../dashboard/DashboardOverview.tsx | 12 ++-- .../src/components/editor/EditorPreview.tsx | 4 +- .../src/components/editor/HistoryControls.tsx | 4 +- .../components/editor/IngredientEditor.tsx | 4 +- .../components/editor/InstructionEditor.tsx | 4 +- .../src/components/editor/RecipeEditor.tsx | 4 +- .../src/components/features/FeatureMap.tsx | 4 +- examples/nextjs/src/components/nav/NavBar.tsx | 4 +- .../nextjs/src/components/nav/ThemeToggle.tsx | 4 +- .../src/components/planner/MealSlotPicker.tsx | 4 +- .../src/components/planner/PlannerGrid.tsx | 6 +- .../src/components/planner/PlannerStats.tsx | 6 +- .../src/components/recipes/RecipeCard.tsx | 6 +- .../src/components/recipes/RecipeFilter.tsx | 8 +-- .../src/components/recipes/RecipeList.tsx | 10 +-- .../src/components/recipes/TagManager.tsx | 6 +- .../src/components/settings/SettingsForm.tsx | 9 ++- .../src/components/shopping/ShoppingList.tsx | 8 +-- .../src/components/shopping/ShoppingStats.tsx | 8 +-- .../src/demos/collections/CollectionsDemo.tsx | 14 ++-- .../react/src/demos/devtools/DevtoolsDemo.tsx | 4 +- .../react/src/demos/history/UndoRedoDemo.tsx | 8 +-- .../demos/local-store/LocalCounterDemo.tsx | 6 +- .../demos/persist/KitchenSinkPersistDemo.tsx | 19 +++--- .../src/demos/persist/SimplePersistDemo.tsx | 15 +++-- .../react/src/demos/reactivity/AsyncDemo.tsx | 18 +++--- .../reactivity/ReactiveFundamentalsDemo.tsx | 14 ++-- .../demos/shallow-equal/ShallowEqualDemo.tsx | 12 ++-- .../demos/snapshots/StructuralSharingDemo.tsx | 4 +- .../demos/subscribe-key/SubscribeKeyDemo.tsx | 4 +- examples/react/src/pages/OverviewPage.tsx | 8 +-- examples/react/src/pages/ReactivityPage.tsx | 2 +- examples/react/src/pages/ShallowEqualPage.tsx | 4 +- examples/solid/src/App.tsx | 4 +- examples/vue/src/App.vue | 4 +- .../classy-store/src/core/computed.test.tsx | 12 ++-- .../frameworks/react/react.behavior.test.tsx | 62 +++++++++--------- .../src/frameworks/react/react.test.tsx | 64 +++++++++---------- .../src/frameworks/react/react.ts | 10 +-- .../src/frameworks/solid/solid.ts | 4 +- .../classy-store/src/frameworks/vue/vue.ts | 2 +- .../src/utils/equality/equality.ts | 2 +- website/docs/ARCHITECTURE.md | 20 +++--- website/docs/HISTORY_TUTORIAL.md | 2 +- website/docs/PERSIST_ARCHITECTURE.md | 4 +- website/docs/TUTORIAL.md | 46 ++++++------- website/docs/index.md | 52 +++++++-------- website/src/pages/index.tsx | 4 +- 51 files changed, 290 insertions(+), 272 deletions(-) create mode 100644 .changeset/petite-wombats-count.md diff --git a/.changeset/petite-wombats-count.md b/.changeset/petite-wombats-count.md new file mode 100644 index 0000000..8157a27 --- /dev/null +++ b/.changeset/petite-wombats-count.md @@ -0,0 +1,5 @@ +--- +"@codebelt/classy-store": minor +--- + +refactor: rename `useStore` to `useClassyStore` diff --git a/CLAUDE.md b/CLAUDE.md index 6a39f69..c8c6129 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,10 +17,10 @@ packages/classy-store/src/ ├── collections/collections.ts # ReactiveMap and ReactiveSet (array-backed Map/Set emulation) ├── collections/index.ts # Collections barrel: reactiveMap, reactiveSet, ReactiveMap, ReactiveSet ├── frameworks/ -│ ├── react/react.ts # Layer 3 (React): useStore(), useLocalStore() via useSyncExternalStore -│ ├── vue/vue.ts # Vue: useStore() → ShallowRef> (onUnmounted cleanup) +│ ├── react/react.ts # Layer 3 (React): useClassyStore(), useLocalStore() via useSyncExternalStore +│ ├── vue/vue.ts # Vue: useClassyStore() → ShallowRef> (onUnmounted cleanup) │ ├── svelte/svelte.ts # Svelte: toSvelteStore() → ClassyReadable> -│ ├── solid/solid.ts # Solid: useStore() → () => Snapshot signal (onCleanup) +│ ├── solid/solid.ts # Solid: useClassyStore() → () => Snapshot signal (onCleanup) │ └── angular/angular.ts # Angular: injectStore() → Signal> (DestroyRef) └── utils/ ├── index.ts # Utils barrel: persist, devtools, subscribeKey, withHistory @@ -101,7 +101,7 @@ Enforced by Biome 2.4.0 (`biome.json` at repo root): - **Computed memoization:** two layers — the write proxy caches getter results keyed on dependency versions/values; the snapshot layer adds cross-snapshot caching using structural sharing reference equality. - **Structural sharing:** unchanged sub-trees reuse the previous frozen snapshot reference. This makes `Object.is` comparisons in selectors efficient without `shallowEqual`. - **Version numbers:** monotonically increasing integers stored per proxy node. Child mutations propagate version bumps up to the root. The snapshot cache is keyed on version — a cache hit is O(1). -- **React auto-tracking:** `useStore(store)` (no selector) wraps the snapshot in a `proxy-compare` tracking proxy. Only properties the component actually reads trigger re-renders. `proxy-compare` is the library's only production dependency. +- **React auto-tracking:** `useClassyStore(store)` (no selector) wraps the snapshot in a `proxy-compare` tracking proxy. Only properties the component actually reads trigger re-renders. `proxy-compare` is the library's only production dependency. ## Package Export Entry Points @@ -109,10 +109,10 @@ Enforced by Biome 2.4.0 (`biome.json` at repo root): |---|---| | `@codebelt/classy-store` | `createClassyStore`, `snapshot`, `subscribe`, `getVersion`, `shallowEqual`, `Snapshot` type | | `@codebelt/classy-store/collections` | `reactiveMap`, `reactiveSet`, `ReactiveMap` type, `ReactiveSet` type | -| `@codebelt/classy-store/react` | `useStore`, `useLocalStore` | -| `@codebelt/classy-store/vue` | `useStore` (ShallowRef) | +| `@codebelt/classy-store/react` | `useClassyStore`, `useLocalStore` | +| `@codebelt/classy-store/vue` | `useClassyStore` (ShallowRef) | | `@codebelt/classy-store/svelte` | `toSvelteStore` (ClassyReadable) | -| `@codebelt/classy-store/solid` | `useStore` (signal getter) | +| `@codebelt/classy-store/solid` | `useClassyStore` (signal getter) | | `@codebelt/classy-store/angular` | `injectStore` (Signal) | | `@codebelt/classy-store/utils` | `persist`, `devtools`, `subscribeKey`, `withHistory` | diff --git a/README.md b/README.md index 02daa9b..5369501 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ const cartStore = createClassyStore(new CartStore()); // 3. Use in any framework — React shown here function CartTotal() { - const total = useStore(cartStore, (state) => state.total); + const total = useClassyStore(cartStore, (state) => state.total); return ${total.toFixed(2)}; } @@ -88,7 +88,7 @@ This library wouldn't exist without the ideas pioneered by these projects. Each **[Valtio](https://github.com/pmndrs/valtio)** — Daishi Kato's proxy-based masterpiece gave us the core architectural pattern: a mutable write proxy for ergonomic mutations paired with immutable snapshots for React integration. Valtio's structural sharing approach — where unchanged sub-trees keep the same frozen reference across snapshots — is what makes `Object.is` selectors efficient without custom equality. We also adopted its `proxy-compare` library for automatic property tracking in selectorless mode. -**[Zustand](https://github.com/pmndrs/zustand)** — Also by Daishi Kato, Zustand set the standard for minimal, hook-first state management. Its selector pattern (`useStore(store, s => s.count)`) with `Object.is` equality is what we use in selector mode. Zustand proved that you don't need Providers, context wrappers, or HOCs — just a hook and a store. Its focus on tiny bundle size pushed us to keep things lean. +**[Zustand](https://github.com/pmndrs/zustand)** — Also by Daishi Kato, Zustand set the standard for minimal, hook-first state management. Its selector pattern (`useClassyStore(store, s => s.count)`) with `Object.is` equality is what we use in selector mode. Zustand proved that you don't need Providers, context wrappers, or HOCs — just a hook and a store. Its focus on tiny bundle size pushed us to keep things lean. **[proxy-compare](https://github.com/dai-shi/proxy-compare)** — The ~1KB utility (also by Dai-shi) that powers our auto-tracked mode. It wraps frozen snapshot objects in a tracking proxy, recording which properties a component reads, then efficiently diffs only those properties between snapshots. This eliminates the need for manual selectors in most cases. diff --git a/examples/nextjs/src/components/dashboard/DashboardOverview.tsx b/examples/nextjs/src/components/dashboard/DashboardOverview.tsx index b2539d9..d624bdf 100644 --- a/examples/nextjs/src/components/dashboard/DashboardOverview.tsx +++ b/examples/nextjs/src/components/dashboard/DashboardOverview.tsx @@ -1,7 +1,7 @@ 'use client'; import {shallowEqual} from '@codebelt/classy-store'; -import {useStore} from '@codebelt/classy-store/react'; +import {useClassyStore} from '@codebelt/classy-store/react'; import {ApiInfo} from '@/components/shared/ApiInfo'; import {plannerStore} from '@/stores/planner-store'; import {recipeStore} from '@/stores/recipe-store'; @@ -62,7 +62,7 @@ const Icons = { }; export function DashboardOverview() { - const recipeStats = useStore( + const recipeStats = useClassyStore( recipeStore, (state) => ({ count: state.recipeCount, @@ -71,7 +71,7 @@ export function DashboardOverview() { shallowEqual, ); - const shoppingStats = useStore( + const shoppingStats = useClassyStore( shoppingStore, (state) => ({ total: state.totalItems, @@ -80,7 +80,7 @@ export function DashboardOverview() { shallowEqual, ); - const plannerStats = useStore( + const plannerStats = useClassyStore( plannerStore, (state) => ({ meals: state.totalMealsPlanned, @@ -122,9 +122,9 @@ export function DashboardOverview() {

Overview

({ + code={`const stats = useClassyStore(recipeStore, (state) => ({ count: state.recipeCount, avgTime: state.averageTotalTime, }), shallowEqual);`} diff --git a/examples/nextjs/src/components/editor/EditorPreview.tsx b/examples/nextjs/src/components/editor/EditorPreview.tsx index 9ae5d66..c1a6f73 100644 --- a/examples/nextjs/src/components/editor/EditorPreview.tsx +++ b/examples/nextjs/src/components/editor/EditorPreview.tsx @@ -1,11 +1,11 @@ 'use client'; -import {useStore} from '@codebelt/classy-store/react'; +import {useClassyStore} from '@codebelt/classy-store/react'; import {ApiInfo} from '@/components/shared/ApiInfo'; import type {RecipeEditorStore} from '@/stores/recipe-editor-store'; export function EditorPreview({store}: {store: RecipeEditorStore}) { - const snap = useStore(store); + const snap = useClassyStore(store); return (
diff --git a/examples/nextjs/src/components/editor/HistoryControls.tsx b/examples/nextjs/src/components/editor/HistoryControls.tsx index 9762bca..a475fe2 100644 --- a/examples/nextjs/src/components/editor/HistoryControls.tsx +++ b/examples/nextjs/src/components/editor/HistoryControls.tsx @@ -1,6 +1,6 @@ 'use client'; -import {useStore} from '@codebelt/classy-store/react'; +import {useClassyStore} from '@codebelt/classy-store/react'; import type {HistoryHandle} from '@codebelt/classy-store/utils'; import {ApiInfo} from '@/components/shared/ApiInfo'; @@ -12,7 +12,7 @@ export function HistoryControls({ store: object; }) { // Subscribe to store changes so we re-render when canUndo/canRedo changes. - useStore(store); + useClassyStore(store); return (
diff --git a/examples/nextjs/src/components/editor/IngredientEditor.tsx b/examples/nextjs/src/components/editor/IngredientEditor.tsx index d04f84d..9ce3d2f 100644 --- a/examples/nextjs/src/components/editor/IngredientEditor.tsx +++ b/examples/nextjs/src/components/editor/IngredientEditor.tsx @@ -1,11 +1,11 @@ 'use client'; -import {useStore} from '@codebelt/classy-store/react'; +import {useClassyStore} from '@codebelt/classy-store/react'; import {ApiInfo} from '@/components/shared/ApiInfo'; import type {RecipeEditorStore} from '@/stores/recipe-editor-store'; export function IngredientEditor({store}: {store: RecipeEditorStore}) { - const snap = useStore(store); + const snap = useClassyStore(store); return (
diff --git a/examples/nextjs/src/components/editor/InstructionEditor.tsx b/examples/nextjs/src/components/editor/InstructionEditor.tsx index 265f233..b917fef 100644 --- a/examples/nextjs/src/components/editor/InstructionEditor.tsx +++ b/examples/nextjs/src/components/editor/InstructionEditor.tsx @@ -1,11 +1,11 @@ 'use client'; -import {useStore} from '@codebelt/classy-store/react'; +import {useClassyStore} from '@codebelt/classy-store/react'; import {ApiInfo} from '@/components/shared/ApiInfo'; import type {RecipeEditorStore} from '@/stores/recipe-editor-store'; export function InstructionEditor({store}: {store: RecipeEditorStore}) { - const snap = useStore(store); + const snap = useClassyStore(store); return (
diff --git a/examples/nextjs/src/components/editor/RecipeEditor.tsx b/examples/nextjs/src/components/editor/RecipeEditor.tsx index 6e2dd25..3664138 100644 --- a/examples/nextjs/src/components/editor/RecipeEditor.tsx +++ b/examples/nextjs/src/components/editor/RecipeEditor.tsx @@ -1,6 +1,6 @@ 'use client'; -import {useLocalStore, useStore} from '@codebelt/classy-store/react'; +import {useClassyStore, useLocalStore} from '@codebelt/classy-store/react'; import type {HistoryHandle} from '@codebelt/classy-store/utils'; import {withHistory} from '@codebelt/classy-store/utils'; import {useRef} from 'react'; @@ -17,7 +17,7 @@ export function RecipeEditor() { if (!historyRef.current) { historyRef.current = withHistory(store, {limit: 30}); } - const snap = useStore(store); + const snap = useClassyStore(store); return (
diff --git a/examples/nextjs/src/components/features/FeatureMap.tsx b/examples/nextjs/src/components/features/FeatureMap.tsx index 908292b..581a974 100644 --- a/examples/nextjs/src/components/features/FeatureMap.tsx +++ b/examples/nextjs/src/components/features/FeatureMap.tsx @@ -65,7 +65,7 @@ const sections: FeatureSection[] = [ title: 'React Bindings', rows: [ { - api: 'useStore() auto-tracked', + api: 'useClassyStore() auto-tracked', description: 'Proxy-based tracking \u2014 only re-renders when accessed properties change', links: [ @@ -76,7 +76,7 @@ const sections: FeatureSection[] = [ ], }, { - api: 'useStore() with selector', + api: 'useClassyStore() with selector', description: 'Selector extracts derived values; combined with shallowEqual for efficiency', links: [ diff --git a/examples/nextjs/src/components/nav/NavBar.tsx b/examples/nextjs/src/components/nav/NavBar.tsx index cba5118..a03d918 100644 --- a/examples/nextjs/src/components/nav/NavBar.tsx +++ b/examples/nextjs/src/components/nav/NavBar.tsx @@ -1,6 +1,6 @@ 'use client'; -import {useStore} from '@codebelt/classy-store/react'; +import {useClassyStore} from '@codebelt/classy-store/react'; import Link from 'next/link'; import {usePathname} from 'next/navigation'; import {shoppingStore} from '@/stores/shopping-store'; @@ -17,7 +17,7 @@ const links = [ export function NavBar() { const pathname = usePathname(); - const shoppingSnap = useStore(shoppingStore); + const shoppingSnap = useClassyStore(shoppingStore); return (