Skip to content

Commit d59867f

Browse files
committed
refactor: standardize selector function parameter naming for useStore across codebase
1 parent 493abdd commit d59867f

9 files changed

Lines changed: 55 additions & 43 deletions

File tree

examples/rendering/src/AsyncDemo.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {postStore} from './stores';
55
import {useRenderCount} from './useRenderCount';
66

77
function LoadingIndicator() {
8-
const loading = useStore(postStore, (s) => s.loading);
8+
const loading = useStore(postStore, (store) => store.loading);
99
const renders = useRenderCount();
1010
return (
1111
<div className="flex items-center justify-between bg-amber-500/10 border border-amber-500/20 rounded-lg px-3 py-2.5">
@@ -51,7 +51,7 @@ function LoadingIndicator() {
5151
}
5252

5353
function ErrorDisplay() {
54-
const error = useStore(postStore, (s) => s.error);
54+
const error = useStore(postStore, (store) => store.error);
5555
const renders = useRenderCount();
5656
return (
5757
<div className="flex items-center justify-between bg-red-500/10 border border-red-500/20 rounded-lg px-3 py-2.5">
@@ -71,7 +71,7 @@ function ErrorDisplay() {
7171
}
7272

7373
function PostList() {
74-
const posts = useStore(postStore, (s) => s.posts);
74+
const posts = useStore(postStore, (store) => store.posts);
7575
const renders = useRenderCount();
7676
return (
7777
<div className="bg-emerald-500/10 border border-emerald-500/20 rounded-lg px-3 py-2.5">
@@ -102,7 +102,7 @@ function PostList() {
102102
}
103103

104104
function PostCount() {
105-
const count = useStore(postStore, (s) => s.count);
105+
const count = useStore(postStore, (store) => store.count);
106106
const renders = useRenderCount();
107107
return (
108108
<div className="flex items-center gap-2">

examples/rendering/src/CollectionsDemo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ function TagList() {
107107
}
108108

109109
function CountDisplay() {
110-
const userCount = useStore(collectionStore, (s) => s.userCount);
111-
const tagCount = useStore(collectionStore, (s) => s.tagCount);
110+
const userCount = useStore(collectionStore, (store) => store.userCount);
111+
const tagCount = useStore(collectionStore, (store) => store.tagCount);
112112
const renders = useRenderCount();
113113

114114
return (

examples/rendering/src/ReactiveFundamentalsDemo.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const names = ['World', 'Bun', 'React', 'Store'];
1212
let nameIndex = 0;
1313

1414
function CountCard() {
15-
const count = useStore(counterStore, (s) => s.count);
15+
const count = useStore(counterStore, (store) => store.count);
1616
const renders = useRenderCount();
1717
return (
1818
<div className="flex-1 flex items-center justify-between bg-indigo-500/10 border border-indigo-500/20 rounded-lg px-3 py-2.5">
@@ -30,7 +30,7 @@ function CountCard() {
3030
}
3131

3232
function NameCard() {
33-
const name = useStore(counterStore, (s) => s.name);
33+
const name = useStore(counterStore, (store) => store.name);
3434
const renders = useRenderCount();
3535
return (
3636
<div className="flex-1 flex items-center justify-between bg-violet-500/10 border border-violet-500/20 rounded-lg px-3 py-2.5">
@@ -48,7 +48,7 @@ function NameCard() {
4848
}
4949

5050
function BatchCard() {
51-
const count = useStore(batchStore, (s) => s.count);
51+
const count = useStore(batchStore, (store) => store.count);
5252
const renders = useRenderCount();
5353
return (
5454
<div className="flex-1 flex items-center justify-between bg-amber-500/10 border border-amber-500/20 rounded-lg px-3 py-2.5">

examples/rendering/src/StructuralSharingDemo.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,33 @@ function SnapshotTree() {
8585
<div className="text-xs text-zinc-400 uppercase tracking-wide mb-3">
8686
Snapshot Reference Tree
8787
</div>
88-
<TreeNode label="root" getValue={(s) => s}>
89-
<TreeNode label=".metadata" getValue={(s) => s.metadata} depth={1} />
90-
<TreeNode label=".content" getValue={(s) => s.content} depth={1}>
88+
<TreeNode label="root" getValue={(store) => store}>
89+
<TreeNode
90+
label=".metadata"
91+
getValue={(store) => store.metadata}
92+
depth={1}
93+
/>
94+
<TreeNode
95+
label=".content"
96+
getValue={(store) => store.content}
97+
depth={1}
98+
>
9199
<TreeNode
92100
label=".sections[0]"
93-
getValue={(s) => s.content.sections[0]}
101+
getValue={(store) => store.content.sections[0]}
94102
depth={2}
95103
/>
96104
<TreeNode
97105
label=".sections[1]"
98-
getValue={(s) => s.content.sections[1]}
106+
getValue={(store) => store.content.sections[1]}
99107
depth={2}
100108
/>
101109
</TreeNode>
102-
<TreeNode label=".settings" getValue={(s) => s.settings} depth={1} />
110+
<TreeNode
111+
label=".settings"
112+
getValue={(store) => store.settings}
113+
depth={1}
114+
/>
103115
</TreeNode>
104116
</div>
105117
);

examples/rendering/src/stores.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export class DocumentStore {
8888
}
8989

9090
updateSectionBody(id: number, body: string) {
91-
const section = this.content.sections.find((s) => s.id === id);
91+
const section = this.content.sections.find((store) => store.id === id);
9292
if (section) section.body = body;
9393
}
9494

website/docs/ARCHITECTURE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ flowchart TD
319319
4. For getters reading other getters (e.g., `get filteredCount() { return this.filtered.length; }`): the inner getter is itself memoized, so it returns a stable reference, which the outer getter's dep check recognizes as unchanged.
320320

321321
**Impact on `useStore`:** The existing hook benefits automatically — no changes needed:
322-
- **Selector mode:** `useStore(store, s => s.filtered)` gets a stable reference from the memoized snapshot getter. `Object.is` correctly detects "no change" without `shallowEqual`.
322+
- **Selector mode:** `useStore(store, (store) => store.filtered)` gets a stable reference from the memoized snapshot getter. `Object.is` correctly detects "no change" without `shallowEqual`.
323323
- **Auto-tracked mode:** `proxy-compare`'s `isChanged` gets stable references from snapshot getters, reducing false positives.
324324

325325
## Layer 3: React Hook (`useStore.ts`)
@@ -331,7 +331,7 @@ flowchart TD
331331
### Mode 1: Selector
332332

333333
```typescript
334-
const count = useStore(myStore, s => s.count);
334+
const count = useStore(myStore, (store) => store.count);
335335
```
336336

337337
```mermaid

website/docs/TUTORIAL.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { useStore } from '@codebelt/classy-store/react';
2929
import { counterStore } from './stores';
3030

3131
export function Counter() {
32-
const count = useStore(counterStore, (s) => s.count);
32+
const count = useStore(counterStore, (store) => store.count);
3333
return <button onClick={counterStore.increment}>Count: {count}</button>;
3434
}
3535
```
@@ -87,7 +87,7 @@ Key points:
8787
### Selector mode
8888

8989
```ts
90-
const count = useStore(counterStore, (s) => s.count);
90+
const count = useStore(counterStore, (store) => store.count);
9191
```
9292

9393
The selector receives an immutable snapshot and returns the slice you need. The component re-renders only when the selected value changes (compared with `Object.is`).
@@ -111,8 +111,8 @@ By default, `useStore` compares the selector's return value with `Object.is`, wh
111111

112112
```ts
113113
// ✅ No shallowEqual needed — structural sharing keeps the reference stable
114-
const count = useStore(todoStore, (s) => s.items.length);
115-
const todos = useStore(todoStore, (s) => s.items);
114+
const count = useStore(todoStore, (store) => store.items.length);
115+
const todos = useStore(todoStore, (store) => store.items);
116116
```
117117

118118
The problem shows up when your selector **derives a new value** — calling `.filter()`, `.map()`, or using object spread always allocates a new array or object, even when the underlying data hasn't changed. `Object.is` sees a different reference and triggers a re-render.
@@ -125,7 +125,7 @@ Without `shallowEqual` — `.filter()` creates a new array every time the snapsh
125125
import { useStore } from '@codebelt/classy-store/react';
126126

127127
// ❌ New array reference every snapshot → unnecessary re-renders
128-
const active = useStore(todoStore, (s) => s.items.filter((i) => !i.done));
128+
const active = useStore(todoStore, (store) => store.items.filter((i) => !i.done));
129129
```
130130

131131
With `shallowEqual` — compares the array contents, not the reference:
@@ -137,7 +137,7 @@ import { useStore } from '@codebelt/classy-store/react';
137137
// ✅ Only re-renders when the filtered items actually change
138138
const active = useStore(
139139
todoStore,
140-
(s) => s.items.filter((i) => !i.done),
140+
(store) => store.items.filter((i) => !i.done),
141141
shallowEqual,
142142
);
143143
```
@@ -146,10 +146,10 @@ const active = useStore(
146146

147147
```ts
148148
// ✅ No shallowEqual needed — cross-snapshot memoization keeps getter results stable
149-
const filtered = useStore(todoStore, (s) => s.filtered);
149+
const filtered = useStore(todoStore, (store) => store.filtered);
150150

151151
// ✅ Primitives from getters also work fine
152-
const remaining = useStore(todoStore, (s) => s.remaining);
152+
const remaining = useStore(todoStore, (store) => store.remaining);
153153
```
154154

155155
`shallowEqual` is only needed when the **selector itself** derives a new value (via `.filter()`, `.map()`, object spread, etc.) — not when selecting a getter that does the derivation internally.
@@ -250,7 +250,7 @@ docStore.sections[0].body = 'Updated intro';
250250

251251
While modifying nested properties directly through the proxy works, the same best practice applies here: prefer store methods over inline mutations. When nested updates are scattered across components, it becomes difficult to trace how deeply nested state changes. Methods give you a single place to look.
252252

253-
Structural sharing means that when you mutate `metadata.title`, the snapshot for `sections` is reused from the previous snapshot (same reference). A component selecting `s => s.sections` won't re-render because its selected value hasn't changed.
253+
Structural sharing means that when you mutate `metadata.title`, the snapshot for `sections` is reused from the previous snapshot (same reference). A component selecting `(store) => store.sections` won't re-render because its selected value hasn't changed.
254254

255255
## Collections
256256

@@ -365,7 +365,7 @@ class PostStore {
365365
}
366366
```
367367

368-
This means a component using `useStore(postStore, s => s.loading)` will re-render twice: once when loading starts, once when it ends. That's the correct behavior.
368+
This means a component using `useStore(postStore, (store) => store.loading)` will re-render twice: once when loading starts, once when it ends. That's the correct behavior.
369369

370370
## Tips & Gotchas
371371

@@ -416,7 +416,7 @@ class Counter {
416416
}
417417

418418
// ✅ Selector mode: no re-render (Object.is sees same count value)
419-
const count = useStore(counterStore, (s) => s.count);
419+
const count = useStore(counterStore, (store) => store.count);
420420

421421
// ⚠️ Auto-tracked mode: re-renders (snapshot reference changed)
422422
const snap = useStore(counterStore);

website/docs/index.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ import { useStore } from '@codebelt/classy-store/react';
7373

7474
// Selector mode: explicit control over what triggers re-renders
7575
function TodoCount() {
76-
const remaining = useStore(todoStore, s => s.remaining);
76+
const remaining = useStore(todoStore, (store) => store.remaining);
7777
return <span>{remaining} left</span>;
7878
}
7979

@@ -116,9 +116,9 @@ React hook that subscribes to store changes via `useSyncExternalStore`.
116116
**Selector mode:**
117117

118118
```typescript
119-
const count = useStore(myStore, s => s.count);
120-
const user = useStore(myStore, s => s.user);
121-
const items = useStore(myStore, s => s.items);
119+
const count = useStore(myStore, (store) => store.count);
120+
const user = useStore(myStore, (store) => store.user);
121+
const items = useStore(myStore, (store) => store.items);
122122
```
123123

124124
The selector receives an immutable snapshot. Re-renders only when the selected value changes (via `Object.is` by default, or a custom `isEqual`).
@@ -139,9 +139,9 @@ Returns a tracking proxy. Properties your component reads are automatically trac
139139
import { shallowEqual } from '@codebelt/classy-store';
140140
import { useStore } from '@codebelt/classy-store/react';
141141

142-
const userData = useStore(myStore, s => ({
143-
name: s.user.name,
144-
role: s.user.role,
142+
const userData = useStore(myStore, (store) => ({
143+
name: store.user.name,
144+
role: store.user.role,
145145
}), shallowEqual);
146146
```
147147

@@ -212,7 +212,7 @@ class UserStore {
212212
const userStore = createClassyStore(new UserStore());
213213

214214
function UserList() {
215-
const snap = useStore(userStore, s => [...s.users.entries()]);
215+
const snap = useStore(userStore, (store) => [...store.users.entries()]);
216216
return (
217217
<ul>
218218
{snap.map(([id, user]) => (
@@ -244,7 +244,7 @@ class TagStore {
244244
const tagStore = createClassyStore(new TagStore());
245245

246246
function TagList() {
247-
const tags = useStore(tagStore, s => [...s.tags]);
247+
const tags = useStore(tagStore, (store) => [...store.tags]);
248248
return tags.map(tag => <span key={tag}>{tag}</span>);
249249
}
250250
```
@@ -373,8 +373,8 @@ const authStore = createClassyStore(new AuthStore());
373373
const uiStore = createClassyStore(new UiStore());
374374
375375
function Header() {
376-
const user = useStore(authStore, s => s.currentUser);
377-
const theme = useStore(uiStore, s => s.theme);
376+
const user = useStore(authStore, (store) => store.currentUser);
377+
const theme = useStore(uiStore, (store) => store.theme);
378378
return <header className={theme}>{user?.name}</header>;
379379
}
380380
```
@@ -432,7 +432,7 @@ const settingsStore = createClassyStore(new SettingsStore());
432432
433433
// Only re-renders when push notification setting changes
434434
function PushToggle() {
435-
const push = useStore(settingsStore, s => s.settings.notifications.push);
435+
const push = useStore(settingsStore, (store) => store.settings.notifications.push);
436436
return <Switch checked={push} onChange={() => settingsStore.togglePush()} />;
437437
}
438438
```
@@ -488,7 +488,7 @@ class Store {
488488
```typescript
489489
// Stable reference across re-renders when items/filter haven't changed.
490490
// No shallowEqual required!
491-
const filtered = useStore(myStore, s => s.filtered);
491+
const filtered = useStore(myStore, (store) => store.filtered);
492492
```
493493
494494
### Working with Date and RegExp

website/src/pages/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const counterStore = store(new CounterStore());
2121
2222
// 3. Use it in React with automatic updates
2323
function Counter() {
24-
const count = useStore(counterStore, (s) => s.count);
24+
const count = useStore(counterStore, (store) => store.count);
2525
return (
2626
<button onClick={() => counterStore.increment()}>
2727
Count is {count}

0 commit comments

Comments
 (0)