88
99``` ts
1010// stores.ts
11- import { createClassyStore } from ' @codebelt/classy-store' ;
11+ import {createClassyStore } from ' @codebelt/classy-store' ;
1212
1313class Counter {
1414 count = 0 ;
@@ -25,8 +25,8 @@ export const counterStore = createClassyStore(new Counter());
2525
2626``` tsx
2727// Counter.tsx
28- import { useStore } from ' @codebelt/classy-store/react' ;
29- import { counterStore } from ' ./stores' ;
28+ import {useStore } from ' @codebelt/classy-store/react' ;
29+ import {counterStore } from ' ./stores' ;
3030
3131export function Counter() {
3232 const count = useStore (counterStore , (store ) => store .count );
@@ -41,33 +41,33 @@ That's it. No Provider wrapping your app. The store is a module-level singleton
4141A store is any class instance wrapped with ` createClassyStore() ` . State lives as properties, mutations are plain assignments, and computed values are ` get ` accessors.
4242
4343``` ts
44- import { createClassyStore } from ' @codebelt/classy-store' ;
44+ import {createClassyStore } from ' @codebelt/classy-store' ;
4545
4646class TodoStore {
4747 items: { id: number ; text: string ; done: boolean }[] = [];
4848 filter: ' all' | ' active' | ' done' = ' all' ;
4949
5050 get remaining() {
51- return this .items .filter ((i ) => ! i .done ).length ;
51+ return this .items .filter ((item ) => ! item .done ).length ;
5252 }
5353
5454 get filtered() {
55- if (this .filter === ' active' ) return this .items .filter ((i ) => ! i .done );
56- if (this .filter === ' done' ) return this .items .filter ((i ) => i .done );
55+ if (this .filter === ' active' ) return this .items .filter ((item ) => ! item .done );
56+ if (this .filter === ' done' ) return this .items .filter ((item ) => item .done );
5757 return this .items ;
5858 }
5959
6060 add(text : string ) {
61- this .items .push ({ id: Date .now (), text , done: false });
61+ this .items .push ({id: Date .now (), text , done: false });
6262 }
6363
6464 toggle(id : number ) {
65- const item = this .items .find ((i ) => i .id === id );
65+ const item = this .items .find ((todo ) => todo .id === id );
6666 if (item ) item .done = ! item .done ;
6767 }
6868
6969 remove(id : number ) {
70- this .items = this .items .filter ((i ) => i .id !== id );
70+ this .items = this .items .filter ((todo ) => todo .id !== id );
7171 }
7272}
7373
@@ -122,22 +122,22 @@ The problem shows up when your selector **derives a new value** — calling `.fi
122122Without ` shallowEqual ` — ` .filter() ` creates a new array every time the snapshot updates, even if the todo items haven't changed:
123123
124124``` ts
125- import { useStore } from ' @codebelt/classy-store/react' ;
125+ import {useStore } from ' @codebelt/classy-store/react' ;
126126
127127// ❌ New array reference every snapshot → unnecessary re-renders
128- const active = useStore (todoStore , (store ) => store .items .filter ((i ) => ! i .done ));
128+ const active = useStore (todoStore , (store ) => store .items .filter ((item ) => ! item .done ));
129129```
130130
131131With ` shallowEqual ` — compares the array contents, not the reference:
132132
133133``` ts
134- import { shallowEqual } from ' @codebelt/classy-store' ;
135- import { useStore } from ' @codebelt/classy-store/react' ;
134+ import {shallowEqual } from ' @codebelt/classy-store' ;
135+ import {useStore } from ' @codebelt/classy-store/react' ;
136136
137137// ✅ Only re-renders when the filtered items actually change
138138const active = useStore (
139139 todoStore ,
140- (store ) => store .items .filter ((i ) => ! i .done ),
140+ (store ) => store .items .filter ((item ) => ! item .done ),
141141 shallowEqual ,
142142);
143143```
@@ -196,8 +196,8 @@ Mutations separated by an `await` land in different microtasks and trigger separ
196196` snapshot() ` creates a deeply-frozen, immutable copy of the store's current state.
197197
198198``` ts
199- import { snapshot } from ' @codebelt/classy-store' ;
200- import { counterStore } from ' ./stores' ;
199+ import {snapshot } from ' @codebelt/classy-store' ;
200+ import {counterStore } from ' ./stores' ;
201201
202202const snap = snapshot (counterStore );
203203console .log (snap .count ); // read-only
@@ -213,8 +213,8 @@ Snapshots use structural sharing: unchanged sub-trees return the same frozen ref
213213` subscribe() ` registers a callback that fires once per batched mutation. It returns an unsubscribe function.
214214
215215``` ts
216- import { subscribe , snapshot } from ' @codebelt/classy-store' ;
217- import { counterStore } from ' ./stores' ;
216+ import {subscribe , snapshot } from ' @codebelt/classy-store' ;
217+ import {counterStore } from ' ./stores' ;
218218
219219const unsub = subscribe (counterStore , () => {
220220 const snap = snapshot (counterStore );
@@ -232,10 +232,10 @@ Deep objects and arrays are automatically reactive. You don't need to do anythin
232232
233233``` ts
234234class DocStore {
235- metadata = { title: ' Untitled' , author: ' Anonymous' };
235+ metadata = {title: ' Untitled' , author: ' Anonymous' };
236236 sections = [
237- { id: 1 , heading: ' Intro' , body: ' Hello' },
238- { id: 2 , heading: ' Methods' , body: ' We used proxies.' },
237+ {id: 1 , heading: ' Intro' , body: ' Hello' },
238+ {id: 2 , heading: ' Methods' , body: ' We used proxies.' },
239239 ];
240240}
241241
@@ -257,7 +257,7 @@ Structural sharing means that when you mutate `metadata.title`, the snapshot for
257257Native ` Map ` and ` Set ` aren't plain objects — the proxy can't intercept their internal methods. Use ` reactiveMap() ` and ` reactiveSet() ` instead.
258258
259259``` ts
260- import { createClassyStore , reactiveMap } from ' @codebelt/classy-store' ;
260+ import {createClassyStore , reactiveMap } from ' @codebelt/classy-store' ;
261261
262262class UserStore {
263263 users = reactiveMap <string , { name: string ; role: string }>();
@@ -267,7 +267,7 @@ class UserStore {
267267 }
268268
269269 addUser(id : string , name : string ) {
270- this .users .set (id , { name , role: ' viewer' });
270+ this .users .set (id , {name , role: ' viewer' });
271271 }
272272
273273 removeUser(id : string ) {
@@ -287,7 +287,7 @@ export const userStore = createClassyStore(new UserStore());
287287Subclasses work out of the box — no special API or configuration needed. Methods, getters, and properties from all inheritance levels are fully reactive.
288288
289289``` ts
290- import { createClassyStore } from ' @codebelt/classy-store' ;
290+ import {createClassyStore } from ' @codebelt/classy-store' ;
291291
292292class BaseStore {
293293 loading = false ;
@@ -309,22 +309,22 @@ class BaseStore {
309309class UserStore extends BaseStore {
310310 users: { id: string ; name: string }[] = [];
311311
312+ get activeCount() {
313+ return this .users .length ;
314+ }
315+
312316 async fetchUsers() {
313317 this .setLoading (true ); // base method — reactive
314318 this .setError (null );
315319 try {
316320 const res = await fetch (' /api/users' );
317321 this .users = await res .json ();
318- } catch (err ) {
319- this .setError (err instanceof Error ? err .message : ' Failed' );
322+ } catch (error ) {
323+ this .setError (error instanceof Error ? error .message : ' Failed' );
320324 } finally {
321325 this .setLoading (false );
322326 }
323327 }
324-
325- get activeCount() {
326- return this .users .length ;
327- }
328328}
329329
330330export const userStore = createClassyStore (new UserStore ());
@@ -356,8 +356,8 @@ class PostStore {
356356 const res = await fetch (' /api/posts' );
357357 if (! res .ok ) throw new Error (` HTTP ${res .status } ` );
358358 this .posts = await res .json (); // no notification yet — batched with finally
359- } catch (e ) {
360- this .error = e instanceof Error ? e .message : ' Unknown error' ;
359+ } catch (error ) {
360+ this .error = error instanceof Error ? error .message : ' Unknown error' ;
361361 } finally {
362362 this .loading = false ; // notification 2: hides spinner, shows data or error
363363 }
@@ -389,7 +389,7 @@ Destructuring copies the primitive value at that moment and breaks the proxy con
389389
390390``` ts
391391// ❌ Breaks reactivity — `count` is just the number 0
392- const { count } = counterStore ;
392+ const {count} = counterStore ;
393393
394394// ✅ Always access through the proxy
395395counterStore .count ;
@@ -443,7 +443,7 @@ class Counter {
443443Calling ` snapshot() ` multiple times without intervening mutations returns the same frozen object — an O(1) cache hit. There's no cost to calling it liberally.
444444
445445``` ts
446- import { snapshot } from ' @codebelt/classy-store' ;
446+ import {snapshot } from ' @codebelt/classy-store' ;
447447
448448const a = snapshot (counterStore );
449449const b = snapshot (counterStore );
@@ -460,7 +460,7 @@ a === c; // false — new snapshot after mutation
460460` persist() ` saves your store's state to ` localStorage ` (or any storage adapter) and restores it on page load. It's a standalone utility function — import it from ` @codebelt/classy-store/utils ` .
461461
462462``` ts
463- import { persist } from ' @codebelt/classy-store/utils' ;
463+ import {persist } from ' @codebelt/classy-store/utils' ;
464464
465465const handle = persist (todoStore , {
466466 name: ' todo-store' ,
0 commit comments