From 34bd2d95c8001a118b0fb33fd6e32cf6f4dce4ef Mon Sep 17 00:00:00 2001 From: AbdulAzeez Date: Tue, 11 Mar 2025 14:41:49 +0100 Subject: [PATCH 1/5] feat: enhance Derived class with auto-mounting and unmounting logic --- packages/store/src/derived.ts | 73 +++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/packages/store/src/derived.ts b/packages/store/src/derived.ts index 07b25421..6c4cf8bf 100644 --- a/packages/store/src/derived.ts +++ b/packages/store/src/derived.ts @@ -4,26 +4,26 @@ import type { Listener } from './types' export type UnwrapDerivedOrStore = T extends Derived - ? InnerD - : T extends Store - ? InnerS - : never + ? InnerD + : T extends Store + ? InnerS + : never type UnwrapReadonlyDerivedOrStoreArray< TArr extends ReadonlyArray | Store>, > = TArr extends readonly [infer Head, ...infer Tail] ? Head extends Derived | Store - ? Tail extends ReadonlyArray | Store> - ? [UnwrapDerivedOrStore, ...UnwrapReadonlyDerivedOrStoreArray] - : [] - : [] + ? Tail extends ReadonlyArray | Store> + ? [UnwrapDerivedOrStore, ...UnwrapReadonlyDerivedOrStoreArray] + : [] + : [] : [] // Can't have currVal, as it's being evaluated from the current derived fn export interface DerivedFnProps< TArr extends ReadonlyArray | Store> = ReadonlyArray, TUnwrappedArr extends - UnwrapReadonlyDerivedOrStoreArray = UnwrapReadonlyDerivedOrStoreArray, + UnwrapReadonlyDerivedOrStoreArray = UnwrapReadonlyDerivedOrStoreArray, > { // `undefined` if it's the first run /** @@ -69,6 +69,11 @@ export class Derived< _subscriptions: Array<() => void> = [] lastSeenDepValues: Array = [] + + // Add a new field to track mounting state + private _isMounted = false + private _cleanupFn: (() => void) | null = null + getDepVals = () => { const prevDepVals = [] as Array const currDepVals = [] as Array @@ -91,6 +96,8 @@ export class Derived< prevVal: undefined, currDepVals: this.getDepVals().currDepVals as never, }) + + // ❌ No auto-mount here! subscribe() will handle it, because it is better to mount only when needed } registerOnGraph( @@ -175,24 +182,56 @@ export class Derived< } } + /** + * @deprecated Use subscribe() instead, which automatically mounts when needed + */ mount = () => { - this.registerOnGraph() - this.checkIfRecalculationNeededDeeply() - - return () => { - this.unregisterFromGraph() - for (const cleanup of this._subscriptions) { - cleanup() - } + if (!this._isMounted) { + this._mount() } + return this._cleanupFn || (() => { }) } subscribe = (listener: Listener) => { + // Auto-mount if this is the first listener + if (this.listeners.size === 0 && !this._isMounted) { + this._mount() + } + this.listeners.add(listener) const unsub = this.options.onSubscribe?.(listener, this) return () => { this.listeners.delete(listener) unsub?.() + + // Auto-unmount only if this was the last listener, and it wasn't manually mounted + if (this.listeners.size === 0 && this._isMounted) { + this._unmount() + } + } + } + + // Private mount implementation + private _mount = () => { + if (this._isMounted) return + + this.registerOnGraph() + this.checkIfRecalculationNeededDeeply() + + this._isMounted = true + this._cleanupFn = () => { + this.unregisterFromGraph() + for (const cleanup of this._subscriptions) { + cleanup() + } + this._isMounted = false + this._cleanupFn = null } } + + // Private unmount implementation + private _unmount = () => { + if (!this._isMounted || !this._cleanupFn) return + this._cleanupFn() + } } From 6ce0b96d4263a7e4b297f37a43e262c184c2c839 Mon Sep 17 00:00:00 2001 From: AbdulAzeez Date: Tue, 11 Mar 2025 14:41:58 +0100 Subject: [PATCH 2/5] refactor(tests): remove unnecessary mount calls in Derived tests --- packages/store/tests/derived.test.ts | 203 +++++++++++++++------------ 1 file changed, 114 insertions(+), 89 deletions(-) diff --git a/packages/store/tests/derived.test.ts b/packages/store/tests/derived.test.ts index 00a919b6..ccbe7fbe 100644 --- a/packages/store/tests/derived.test.ts +++ b/packages/store/tests/derived.test.ts @@ -32,7 +32,7 @@ describe('Derived', () => { }, }) - doubleCount.mount() + // doubleCount.mount() - No longer needed const sumDoubleHalfCount = new Derived({ deps: [halfCount, doubleCount], @@ -41,7 +41,7 @@ describe('Derived', () => { }, }) - sumDoubleHalfCount.mount() + // sumDoubleHalfCount.mount() - No longer needed const halfCountFn = viFnSubscribe(halfCount) const doubleCountFn = viFnSubscribe(doubleCount) @@ -117,7 +117,7 @@ describe('Derived', () => { }, }) - doubleCount.mount() + // doubleCount.mount() - No longer needed const tripleCount = new Derived({ deps: [count, doubleCount], @@ -126,7 +126,7 @@ describe('Derived', () => { }, }) - tripleCount.mount() + // tripleCount.mount() - No longer needed const doubleCountFn = viFnSubscribe(doubleCount) const tripleCountFn = viFnSubscribe(tripleCount) @@ -150,122 +150,153 @@ describe('Derived', () => { return store.state * 2 }, }) - derived.mount() + // derived.mount() No longer needed const fn = vi.fn() derived.subscribe(fn) store.setState(() => 24) expect(fn).toBeCalledWith({ prevVal: 24, currentVal: 48 }) }) - test('derivedFn should receive old and new dep values', () => { - const count = new Store(12) - const date = new Date() - const time = new Store(date) - const fn = vi.fn() + + test('derivedFn should receive old and new dep values', async () => { + const count = new Store(12); + const time = new Store(new Date()); + + const fn = vi.fn(); + const derived = new Derived({ deps: [count, time], fn: ({ prevDepVals, currDepVals }) => { - fn({ prevDepVals, currDepVals }) - return void 0 + fn({ prevDepVals, currDepVals }); + return void 0; }, - }) - derived.mount() - expect(fn).toBeCalledWith({ + }); + + derived.subscribe(() => { }); + + // First call should be with initial values + expect(fn).toHaveBeenCalledWith({ prevDepVals: undefined, - currDepVals: [12, date], - }) - count.setState(() => 24) - expect(fn).toBeCalledWith({ - prevDepVals: [12, date], - currDepVals: [24, date], - }) - }) + currDepVals: [12, time.state], + }); + + count.setState(() => 24); + + // Expect function to be called with updated values + expect(fn).toHaveBeenCalledWith({ + prevDepVals: [12, time.state], + currDepVals: [24, time.state], + }); + }); + + + test('derivedFn should receive old and new dep values for similar derived values', async () => { + const count = new Store(12); - test('derivedFn should receive old and new dep values for similar derived values', () => { - const count = new Store(12) const halfCount = new Derived({ deps: [count], fn: () => count.state / 2, - }) - halfCount.mount() - const fn = vi.fn() + }); + + // Ensure halfCount subscribes to count + halfCount.subscribe(() => { }); + + const fn = vi.fn(); + const derived = new Derived({ deps: [count, halfCount], fn: ({ prevDepVals, currDepVals }) => { - fn({ prevDepVals, currDepVals }) - return void 0 + fn({ prevDepVals, currDepVals }); + return void 0; }, - }) - derived.mount() - expect(fn).toBeCalledWith({ + }); + + derived.subscribe(() => { }); + + // First call should be with initial values + expect(fn).toHaveBeenCalledWith({ prevDepVals: undefined, - currDepVals: [12, 6], - }) - count.setState(() => 24) - expect(fn).toBeCalledWith({ + currDepVals: [12, 6], // halfCount = 12 / 2 = 6 + }); + + count.setState(() => 24); + + // Expect function to be called with updated values + expect(fn).toHaveBeenCalledWith({ prevDepVals: [12, 6], - currDepVals: [24, 12], - }) - }) + currDepVals: [24, 12], // halfCount = 24 / 2 = 12 + }); + }); + + test('derivedFn should receive the old value', async () => { + const count = new Store(12); + const date = new Date(); + const time = new Store(date); + const fn = vi.fn(); - test('derivedFn should receive the old value', () => { - const count = new Store(12) - const date = new Date() - const time = new Store(date) - const fn = vi.fn() const derived = new Derived({ deps: [count, time], fn: ({ prevVal }) => { - fn(prevVal) - return count.state + fn(prevVal); + return count.state; }, - }) - derived.mount() - expect(fn).toBeCalledWith(undefined) - count.setState(() => 24) - expect(fn).toBeCalledWith(12) - }) + }); + + // Ensure derived subscribes and tracks changes + derived.subscribe(() => { }); + + // First call should use `undefined` + expect(fn).toHaveBeenCalledWith(undefined); + + count.setState(() => 24); + + expect(fn).toHaveBeenCalledWith(12); + }); + - test('should be able to mount and unmount correctly repeatly', () => { + test('should update only when subscribed', () => { const count = new Store(12) const derived = new Derived({ deps: [count], - fn: () => { - return count.state * 2 - }, + fn: () => count.state * 2, }) - const cleanup1 = derived.mount() - cleanup1() - const cleanup2 = derived.mount() - cleanup2() - const cleanup3 = derived.mount() - cleanup3() - derived.mount() + const unsubscribe1 = derived.subscribe(() => { }) + unsubscribe1() + const unsubscribe2 = derived.subscribe(() => { }) + unsubscribe2() + + // Keep at least one active subscription + const unsubscribe3 = derived.subscribe(() => { }) count.setState(() => 24) expect(count.state).toBe(24) expect(derived.state).toBe(48) + + unsubscribe3() // Cleanup }) + + test('should handle calculating state before the derived state is mounted', () => { const count = new Store(12) const derived = new Derived({ deps: [count], - fn: () => { - return count.state * 2 - }, + fn: () => count.state * 2, }) count.setState(() => 24) - derived.mount() + // Force derived to update by subscribing + const unsubscribe = derived.subscribe(() => { }) + unsubscribe() expect(count.state).toBe(24) expect(derived.state).toBe(48) }) + test('should not recompute more than is needed', () => { const fn = vi.fn() const count = new Store(12) @@ -285,7 +316,7 @@ describe('Derived', () => { unmount2() const unmount3 = derived.mount() unmount3() - derived.mount() + // derived.mount() - No longer needed expect(count.state).toBe(24) expect(derived.state).toBe(48) @@ -297,55 +328,49 @@ describe('Derived', () => { const double = new Derived({ deps: [count], - fn: () => { - return count.state * 2 - }, + fn: () => count.state * 2, }) const halfDouble = new Derived({ deps: [double], - fn: () => { - return double.state / 2 - }, + fn: () => double.state / 2, }) - halfDouble.mount() - double.mount() - + // Force computation by subscribing + const unsubscribe = halfDouble.subscribe(() => { }) count.setState(() => 24) + unsubscribe() expect(count.state).toBe(24) expect(double.state).toBe(48) expect(halfDouble.state).toBe(24) }) + test('should be able to mount in the wrong order and still work with a derived and a non-derived state', () => { const count = new Store(12) const double = new Derived({ deps: [count], - fn: () => { - return count.state * 2 - }, + fn: () => count.state * 2, }) const countPlusDouble = new Derived({ deps: [count, double], - fn: () => { - return count.state + double.state - }, + fn: () => count.state + double.state, }) - countPlusDouble.mount() - double.mount() - + // Subscribe to countPlusDouble to trigger the full dependency chain + const unsubscribe = countPlusDouble.subscribe(() => { }) count.setState(() => 24) + unsubscribe() expect(count.state).toBe(24) expect(double.state).toBe(48) expect(countPlusDouble.state).toBe(24 + 48) }) + test('should recompute in the right order', () => { const count = new Store(12) @@ -367,8 +392,8 @@ describe('Derived', () => { }, }) - halfDouble.mount() - double.mount() + // halfDouble.mount() - No longer needed + // double.mount() - No longer needed expect(fn).toHaveBeenLastCalledWith(3) }) From 0598842a981096b0bfb171bdd9bb998eaf27f4e7 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 17:18:54 +0000 Subject: [PATCH 3/5] ci: apply automated fixes and generate docs --- docs/reference/classes/derived.md | 232 ------------------ docs/reference/classes/effect.md | 48 ---- docs/reference/classes/store.md | 124 ---------- docs/reference/functions/batch.md | 24 -- docs/reference/index.md | 34 --- docs/reference/interfaces/derivedfnprops.md | 50 ---- docs/reference/interfaces/derivedoptions.md | 92 ------- docs/reference/interfaces/storeoptions.md | 96 -------- .../type-aliases/unwrapderivedorstore.md | 18 -- .../variables/depsthathavewrittenthistick.md | 24 -- docs/reference/variables/derivedtostore.md | 14 -- docs/reference/variables/storetoderived.md | 28 --- packages/store/src/derived.ts | 20 +- packages/store/tests/derived.test.ts | 90 ++++--- 14 files changed, 51 insertions(+), 843 deletions(-) delete mode 100644 docs/reference/classes/derived.md delete mode 100644 docs/reference/classes/effect.md delete mode 100644 docs/reference/classes/store.md delete mode 100644 docs/reference/functions/batch.md delete mode 100644 docs/reference/index.md delete mode 100644 docs/reference/interfaces/derivedfnprops.md delete mode 100644 docs/reference/interfaces/derivedoptions.md delete mode 100644 docs/reference/interfaces/storeoptions.md delete mode 100644 docs/reference/type-aliases/unwrapderivedorstore.md delete mode 100644 docs/reference/variables/depsthathavewrittenthistick.md delete mode 100644 docs/reference/variables/derivedtostore.md delete mode 100644 docs/reference/variables/storetoderived.md diff --git a/docs/reference/classes/derived.md b/docs/reference/classes/derived.md deleted file mode 100644 index 21733d1d..00000000 --- a/docs/reference/classes/derived.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -id: Derived -title: Derived ---- - - - -# Class: Derived\ - -Defined in: [derived.ts:54](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L54) - -## Type Parameters - -• **TState** - -• **TArr** *extends* `ReadonlyArray`\<[`Derived`](derived.md)\<`any`\> \| [`Store`](store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> - -## Constructors - -### new Derived() - -```ts -new Derived(options): Derived -``` - -Defined in: [derived.ts:87](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L87) - -#### Parameters - -##### options - -[`DerivedOptions`](../interfaces/derivedoptions.md)\<`TState`, `TArr`\> - -#### Returns - -[`Derived`](derived.md)\<`TState`, `TArr`\> - -## Properties - -### lastSeenDepValues - -```ts -lastSeenDepValues: unknown[] = []; -``` - -Defined in: [derived.ts:71](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L71) - -*** - -### listeners - -```ts -listeners: Set>; -``` - -Defined in: [derived.ts:60](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L60) - -*** - -### options - -```ts -options: DerivedOptions; -``` - -Defined in: [derived.ts:63](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L63) - -*** - -### prevState - -```ts -prevState: undefined | TState; -``` - -Defined in: [derived.ts:62](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L62) - -*** - -### state - -```ts -state: TState; -``` - -Defined in: [derived.ts:61](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L61) - -## Methods - -### checkIfRecalculationNeededDeeply() - -```ts -checkIfRecalculationNeededDeeply(): void -``` - -Defined in: [derived.ts:157](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L157) - -#### Returns - -`void` - -*** - -### getDepVals() - -```ts -getDepVals(): object -``` - -Defined in: [derived.ts:72](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L72) - -#### Returns - -`object` - -##### currDepVals - -```ts -currDepVals: unknown[]; -``` - -##### prevDepVals - -```ts -prevDepVals: unknown[]; -``` - -##### prevVal - -```ts -prevVal: undefined | NonNullable; -``` - -*** - -### mount() - -```ts -mount(): () => void -``` - -Defined in: [derived.ts:178](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L178) - -#### Returns - -`Function` - -##### Returns - -`void` - -*** - -### recompute() - -```ts -recompute(): void -``` - -Defined in: [derived.ts:145](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L145) - -#### Returns - -`void` - -*** - -### registerOnGraph() - -```ts -registerOnGraph(deps): void -``` - -Defined in: [derived.ts:96](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L96) - -#### Parameters - -##### deps - -readonly ( - \| [`Derived`](derived.md)\<`any`, readonly `any`[]\> - \| [`Store`](store.md)\<`any`, (`cb`) => `any`\>)[] = `...` - -#### Returns - -`void` - -*** - -### subscribe() - -```ts -subscribe(listener): () => void -``` - -Defined in: [derived.ts:190](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L190) - -#### Parameters - -##### listener - -`Listener`\<`TState`\> - -#### Returns - -`Function` - -##### Returns - -`void` - -*** - -### unregisterFromGraph() - -```ts -unregisterFromGraph(deps): void -``` - -Defined in: [derived.ts:125](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L125) - -#### Parameters - -##### deps - -readonly ( - \| [`Derived`](derived.md)\<`any`, readonly `any`[]\> - \| [`Store`](store.md)\<`any`, (`cb`) => `any`\>)[] = `...` - -#### Returns - -`void` diff --git a/docs/reference/classes/effect.md b/docs/reference/classes/effect.md deleted file mode 100644 index 333ddc0b..00000000 --- a/docs/reference/classes/effect.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: Effect -title: Effect ---- - - - -# Class: Effect - -Defined in: [effect.ts:17](https://github.com/TanStack/store/blob/main/packages/store/src/effect.ts#L17) - -## Constructors - -### new Effect() - -```ts -new Effect(opts): Effect -``` - -Defined in: [effect.ts:23](https://github.com/TanStack/store/blob/main/packages/store/src/effect.ts#L23) - -#### Parameters - -##### opts - -`EffectOptions` - -#### Returns - -[`Effect`](effect.md) - -## Methods - -### mount() - -```ts -mount(): () => void -``` - -Defined in: [effect.ts:39](https://github.com/TanStack/store/blob/main/packages/store/src/effect.ts#L39) - -#### Returns - -`Function` - -##### Returns - -`void` diff --git a/docs/reference/classes/store.md b/docs/reference/classes/store.md deleted file mode 100644 index ee32ec43..00000000 --- a/docs/reference/classes/store.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -id: Store -title: Store ---- - - - -# Class: Store\ - -Defined in: [store.ts:27](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L27) - -## Type Parameters - -• **TState** - -• **TUpdater** *extends* `AnyUpdater` = (`cb`) => `TState` - -## Constructors - -### new Store() - -```ts -new Store(initialState, options?): Store -``` - -Defined in: [store.ts:36](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L36) - -#### Parameters - -##### initialState - -`TState` - -##### options? - -[`StoreOptions`](../interfaces/storeoptions.md)\<`TState`, `TUpdater`\> - -#### Returns - -[`Store`](store.md)\<`TState`, `TUpdater`\> - -## Properties - -### listeners - -```ts -listeners: Set>; -``` - -Defined in: [store.ts:31](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L31) - -*** - -### options? - -```ts -optional options: StoreOptions; -``` - -Defined in: [store.ts:34](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L34) - -*** - -### prevState - -```ts -prevState: TState; -``` - -Defined in: [store.ts:33](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L33) - -*** - -### state - -```ts -state: TState; -``` - -Defined in: [store.ts:32](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L32) - -## Methods - -### setState() - -```ts -setState(updater): void -``` - -Defined in: [store.ts:51](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L51) - -#### Parameters - -##### updater - -`TUpdater` - -#### Returns - -`void` - -*** - -### subscribe() - -```ts -subscribe(listener): () => void -``` - -Defined in: [store.ts:42](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L42) - -#### Parameters - -##### listener - -`Listener`\<`TState`\> - -#### Returns - -`Function` - -##### Returns - -`void` diff --git a/docs/reference/functions/batch.md b/docs/reference/functions/batch.md deleted file mode 100644 index c2075157..00000000 --- a/docs/reference/functions/batch.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: batch -title: batch ---- - - - -# Function: batch() - -```ts -function batch(fn): void -``` - -Defined in: [scheduler.ts:140](https://github.com/TanStack/store/blob/main/packages/store/src/scheduler.ts#L140) - -## Parameters - -### fn - -() => `void` - -## Returns - -`void` diff --git a/docs/reference/index.md b/docs/reference/index.md deleted file mode 100644 index e8ffd4ca..00000000 --- a/docs/reference/index.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: "@tanstack/store" -title: "@tanstack/store" ---- - - - -# @tanstack/store - -## Classes - -- [Derived](classes/derived.md) -- [Effect](classes/effect.md) -- [Store](classes/store.md) - -## Interfaces - -- [DerivedFnProps](interfaces/derivedfnprops.md) -- [DerivedOptions](interfaces/derivedoptions.md) -- [StoreOptions](interfaces/storeoptions.md) - -## Type Aliases - -- [UnwrapDerivedOrStore](type-aliases/unwrapderivedorstore.md) - -## Variables - -- [\_\_depsThatHaveWrittenThisTick](variables/depsthathavewrittenthistick.md) -- [\_\_derivedToStore](variables/derivedtostore.md) -- [\_\_storeToDerived](variables/storetoderived.md) - -## Functions - -- [batch](functions/batch.md) diff --git a/docs/reference/interfaces/derivedfnprops.md b/docs/reference/interfaces/derivedfnprops.md deleted file mode 100644 index 389a19e0..00000000 --- a/docs/reference/interfaces/derivedfnprops.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: DerivedFnProps -title: DerivedFnProps ---- - - - -# Interface: DerivedFnProps\ - -Defined in: [derived.ts:23](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L23) - -## Type Parameters - -• **TArr** *extends* `ReadonlyArray`\< - \| [`Derived`](../classes/derived.md)\<`any`\> - \| [`Store`](../classes/store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> - -• **TUnwrappedArr** *extends* `UnwrapReadonlyDerivedOrStoreArray`\<`TArr`\> = `UnwrapReadonlyDerivedOrStoreArray`\<`TArr`\> - -## Properties - -### currDepVals - -```ts -currDepVals: TUnwrappedArr; -``` - -Defined in: [derived.ts:35](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L35) - -*** - -### prevDepVals - -```ts -prevDepVals: undefined | TUnwrappedArr; -``` - -Defined in: [derived.ts:34](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L34) - -*** - -### prevVal - -```ts -prevVal: unknown; -``` - -Defined in: [derived.ts:33](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L33) - -`undefined` if it's the first run diff --git a/docs/reference/interfaces/derivedoptions.md b/docs/reference/interfaces/derivedoptions.md deleted file mode 100644 index e062122e..00000000 --- a/docs/reference/interfaces/derivedoptions.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -id: DerivedOptions -title: DerivedOptions ---- - - - -# Interface: DerivedOptions\ - -Defined in: [derived.ts:38](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L38) - -## Type Parameters - -• **TState** - -• **TArr** *extends* `ReadonlyArray`\< - \| [`Derived`](../classes/derived.md)\<`any`\> - \| [`Store`](../classes/store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> - -## Properties - -### deps - -```ts -deps: TArr; -``` - -Defined in: [derived.ts:47](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L47) - -*** - -### fn() - -```ts -fn: (props) => TState; -``` - -Defined in: [derived.ts:51](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L51) - -Values of the `deps` from before and after the current invocation of `fn` - -#### Parameters - -##### props - -[`DerivedFnProps`](derivedfnprops.md)\<`TArr`\> - -#### Returns - -`TState` - -*** - -### onSubscribe()? - -```ts -optional onSubscribe: (listener, derived) => () => void; -``` - -Defined in: [derived.ts:42](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L42) - -#### Parameters - -##### listener - -`Listener`\<`TState`\> - -##### derived - -[`Derived`](../classes/derived.md)\<`TState`\> - -#### Returns - -`Function` - -##### Returns - -`void` - -*** - -### onUpdate()? - -```ts -optional onUpdate: () => void; -``` - -Defined in: [derived.ts:46](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L46) - -#### Returns - -`void` diff --git a/docs/reference/interfaces/storeoptions.md b/docs/reference/interfaces/storeoptions.md deleted file mode 100644 index 81a1256d..00000000 --- a/docs/reference/interfaces/storeoptions.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -id: StoreOptions -title: StoreOptions ---- - - - -# Interface: StoreOptions\ - -Defined in: [store.ts:4](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L4) - -## Type Parameters - -• **TState** - -• **TUpdater** *extends* `AnyUpdater` = (`cb`) => `TState` - -## Properties - -### onSubscribe()? - -```ts -optional onSubscribe: (listener, store) => () => void; -``` - -Defined in: [store.ts:17](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L17) - -Called when a listener subscribes to the store. - -#### Parameters - -##### listener - -`Listener`\<`TState`\> - -##### store - -[`Store`](../classes/store.md)\<`TState`, `TUpdater`\> - -#### Returns - -`Function` - -a function to unsubscribe the listener - -##### Returns - -`void` - -*** - -### onUpdate()? - -```ts -optional onUpdate: () => void; -``` - -Defined in: [store.ts:24](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L24) - -Called after the state has been updated, used to derive other state. - -#### Returns - -`void` - -*** - -### updateFn()? - -```ts -optional updateFn: (previous) => (updater) => TState; -``` - -Defined in: [store.ts:11](https://github.com/TanStack/store/blob/main/packages/store/src/store.ts#L11) - -Replace the default update function with a custom one. - -#### Parameters - -##### previous - -`TState` - -#### Returns - -`Function` - -##### Parameters - -###### updater - -`TUpdater` - -##### Returns - -`TState` diff --git a/docs/reference/type-aliases/unwrapderivedorstore.md b/docs/reference/type-aliases/unwrapderivedorstore.md deleted file mode 100644 index 775273d1..00000000 --- a/docs/reference/type-aliases/unwrapderivedorstore.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: UnwrapDerivedOrStore -title: UnwrapDerivedOrStore ---- - - - -# Type Alias: UnwrapDerivedOrStore\ - -```ts -type UnwrapDerivedOrStore = T extends Derived ? InnerD : T extends Store ? InnerS : never; -``` - -Defined in: [derived.ts:5](https://github.com/TanStack/store/blob/main/packages/store/src/derived.ts#L5) - -## Type Parameters - -• **T** diff --git a/docs/reference/variables/depsthathavewrittenthistick.md b/docs/reference/variables/depsthathavewrittenthistick.md deleted file mode 100644 index 23e5460f..00000000 --- a/docs/reference/variables/depsthathavewrittenthistick.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: __depsThatHaveWrittenThisTick -title: __depsThatHaveWrittenThisTick ---- - - - -# Variable: \_\_depsThatHaveWrittenThisTick - -```ts -const __depsThatHaveWrittenThisTick: object; -``` - -Defined in: [scheduler.ts:28](https://github.com/TanStack/store/blob/main/packages/store/src/scheduler.ts#L28) - -## Type declaration - -### current - -```ts -current: ( - | Derived - | Store unknown>)[]; -``` diff --git a/docs/reference/variables/derivedtostore.md b/docs/reference/variables/derivedtostore.md deleted file mode 100644 index 16ef1e6b..00000000 --- a/docs/reference/variables/derivedtostore.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: __derivedToStore -title: __derivedToStore ---- - - - -# Variable: \_\_derivedToStore - -```ts -const __derivedToStore: WeakMap, Set unknown>>>; -``` - -Defined in: [scheduler.ts:23](https://github.com/TanStack/store/blob/main/packages/store/src/scheduler.ts#L23) diff --git a/docs/reference/variables/storetoderived.md b/docs/reference/variables/storetoderived.md deleted file mode 100644 index b9026ccd..00000000 --- a/docs/reference/variables/storetoderived.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: __storeToDerived -title: __storeToDerived ---- - - - -# Variable: \_\_storeToDerived - -```ts -const __storeToDerived: WeakMap unknown>, Set>>; -``` - -Defined in: [scheduler.ts:19](https://github.com/TanStack/store/blob/main/packages/store/src/scheduler.ts#L19) - -This is here to solve the pyramid dependency problem where: - A - / \ - B C - \ / - D - -Where we deeply traverse this tree, how do we avoid D being recomputed twice; once when B is updated, once when C is. - -To solve this, we create linkedDeps that allows us to sync avoid writes to the state until all of the deps have been -resolved. - -This is a record of stores, because derived stores are not able to write values to, but stores are diff --git a/packages/store/src/derived.ts b/packages/store/src/derived.ts index 6c4cf8bf..1d42d4e0 100644 --- a/packages/store/src/derived.ts +++ b/packages/store/src/derived.ts @@ -4,26 +4,26 @@ import type { Listener } from './types' export type UnwrapDerivedOrStore = T extends Derived - ? InnerD - : T extends Store - ? InnerS - : never + ? InnerD + : T extends Store + ? InnerS + : never type UnwrapReadonlyDerivedOrStoreArray< TArr extends ReadonlyArray | Store>, > = TArr extends readonly [infer Head, ...infer Tail] ? Head extends Derived | Store - ? Tail extends ReadonlyArray | Store> - ? [UnwrapDerivedOrStore, ...UnwrapReadonlyDerivedOrStoreArray] - : [] - : [] + ? Tail extends ReadonlyArray | Store> + ? [UnwrapDerivedOrStore, ...UnwrapReadonlyDerivedOrStoreArray] + : [] + : [] : [] // Can't have currVal, as it's being evaluated from the current derived fn export interface DerivedFnProps< TArr extends ReadonlyArray | Store> = ReadonlyArray, TUnwrappedArr extends - UnwrapReadonlyDerivedOrStoreArray = UnwrapReadonlyDerivedOrStoreArray, + UnwrapReadonlyDerivedOrStoreArray = UnwrapReadonlyDerivedOrStoreArray, > { // `undefined` if it's the first run /** @@ -189,7 +189,7 @@ export class Derived< if (!this._isMounted) { this._mount() } - return this._cleanupFn || (() => { }) + return this._cleanupFn || (() => {}) } subscribe = (listener: Listener) => { diff --git a/packages/store/tests/derived.test.ts b/packages/store/tests/derived.test.ts index ccbe7fbe..fa12ca76 100644 --- a/packages/store/tests/derived.test.ts +++ b/packages/store/tests/derived.test.ts @@ -157,102 +157,99 @@ describe('Derived', () => { expect(fn).toBeCalledWith({ prevVal: 24, currentVal: 48 }) }) - test('derivedFn should receive old and new dep values', async () => { - const count = new Store(12); - const time = new Store(new Date()); + const count = new Store(12) + const time = new Store(new Date()) - const fn = vi.fn(); + const fn = vi.fn() const derived = new Derived({ deps: [count, time], fn: ({ prevDepVals, currDepVals }) => { - fn({ prevDepVals, currDepVals }); - return void 0; + fn({ prevDepVals, currDepVals }) + return void 0 }, - }); + }) - derived.subscribe(() => { }); + derived.subscribe(() => {}) // First call should be with initial values expect(fn).toHaveBeenCalledWith({ prevDepVals: undefined, currDepVals: [12, time.state], - }); + }) - count.setState(() => 24); + count.setState(() => 24) // Expect function to be called with updated values expect(fn).toHaveBeenCalledWith({ prevDepVals: [12, time.state], currDepVals: [24, time.state], - }); - }); - + }) + }) test('derivedFn should receive old and new dep values for similar derived values', async () => { - const count = new Store(12); + const count = new Store(12) const halfCount = new Derived({ deps: [count], fn: () => count.state / 2, - }); + }) // Ensure halfCount subscribes to count - halfCount.subscribe(() => { }); + halfCount.subscribe(() => {}) - const fn = vi.fn(); + const fn = vi.fn() const derived = new Derived({ deps: [count, halfCount], fn: ({ prevDepVals, currDepVals }) => { - fn({ prevDepVals, currDepVals }); - return void 0; + fn({ prevDepVals, currDepVals }) + return void 0 }, - }); + }) - derived.subscribe(() => { }); + derived.subscribe(() => {}) // First call should be with initial values expect(fn).toHaveBeenCalledWith({ prevDepVals: undefined, currDepVals: [12, 6], // halfCount = 12 / 2 = 6 - }); + }) - count.setState(() => 24); + count.setState(() => 24) // Expect function to be called with updated values expect(fn).toHaveBeenCalledWith({ prevDepVals: [12, 6], currDepVals: [24, 12], // halfCount = 24 / 2 = 12 - }); - }); + }) + }) test('derivedFn should receive the old value', async () => { - const count = new Store(12); - const date = new Date(); - const time = new Store(date); - const fn = vi.fn(); + const count = new Store(12) + const date = new Date() + const time = new Store(date) + const fn = vi.fn() const derived = new Derived({ deps: [count, time], fn: ({ prevVal }) => { - fn(prevVal); - return count.state; + fn(prevVal) + return count.state }, - }); + }) // Ensure derived subscribes and tracks changes - derived.subscribe(() => { }); + derived.subscribe(() => {}) // First call should use `undefined` - expect(fn).toHaveBeenCalledWith(undefined); - - count.setState(() => 24); + expect(fn).toHaveBeenCalledWith(undefined) - expect(fn).toHaveBeenCalledWith(12); - }); + count.setState(() => 24) + expect(fn).toHaveBeenCalledWith(12) + }) test('should update only when subscribed', () => { const count = new Store(12) @@ -261,13 +258,13 @@ describe('Derived', () => { fn: () => count.state * 2, }) - const unsubscribe1 = derived.subscribe(() => { }) + const unsubscribe1 = derived.subscribe(() => {}) unsubscribe1() - const unsubscribe2 = derived.subscribe(() => { }) + const unsubscribe2 = derived.subscribe(() => {}) unsubscribe2() // Keep at least one active subscription - const unsubscribe3 = derived.subscribe(() => { }) + const unsubscribe3 = derived.subscribe(() => {}) count.setState(() => 24) @@ -277,8 +274,6 @@ describe('Derived', () => { unsubscribe3() // Cleanup }) - - test('should handle calculating state before the derived state is mounted', () => { const count = new Store(12) const derived = new Derived({ @@ -289,14 +284,13 @@ describe('Derived', () => { count.setState(() => 24) // Force derived to update by subscribing - const unsubscribe = derived.subscribe(() => { }) + const unsubscribe = derived.subscribe(() => {}) unsubscribe() expect(count.state).toBe(24) expect(derived.state).toBe(48) }) - test('should not recompute more than is needed', () => { const fn = vi.fn() const count = new Store(12) @@ -337,7 +331,7 @@ describe('Derived', () => { }) // Force computation by subscribing - const unsubscribe = halfDouble.subscribe(() => { }) + const unsubscribe = halfDouble.subscribe(() => {}) count.setState(() => 24) unsubscribe() @@ -346,7 +340,6 @@ describe('Derived', () => { expect(halfDouble.state).toBe(24) }) - test('should be able to mount in the wrong order and still work with a derived and a non-derived state', () => { const count = new Store(12) @@ -361,7 +354,7 @@ describe('Derived', () => { }) // Subscribe to countPlusDouble to trigger the full dependency chain - const unsubscribe = countPlusDouble.subscribe(() => { }) + const unsubscribe = countPlusDouble.subscribe(() => {}) count.setState(() => 24) unsubscribe() @@ -370,7 +363,6 @@ describe('Derived', () => { expect(countPlusDouble.state).toBe(24 + 48) }) - test('should recompute in the right order', () => { const count = new Store(12) From 23881976a3b6c9977820f7cc9bbcb8e3af7aa446 Mon Sep 17 00:00:00 2001 From: AbdulAzeez Date: Wed, 12 Mar 2025 18:04:53 +0100 Subject: [PATCH 4/5] refactor(tests): comment out unnecessary mount calls in Derived tests --- packages/store/tests/derived.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/store/tests/derived.test.ts b/packages/store/tests/derived.test.ts index ccbe7fbe..9c13a37b 100644 --- a/packages/store/tests/derived.test.ts +++ b/packages/store/tests/derived.test.ts @@ -23,7 +23,7 @@ describe('Derived', () => { }, }) - halfCount.mount() + // halfCount.mount() const doubleCount = new Derived({ deps: [count], @@ -392,6 +392,8 @@ describe('Derived', () => { }, }) + halfDouble.subscribe(() => { }) + // halfDouble.mount() - No longer needed // double.mount() - No longer needed From 478513ecbe45edca834b03350008be0d334d3155 Mon Sep 17 00:00:00 2001 From: AbdulAzeez Date: Wed, 12 Mar 2025 18:12:38 +0100 Subject: [PATCH 5/5] chore(docs): update generated docs --- .../reference/functions/injectstore.md | 4 +- .../react/reference/functions/shallow.md | 2 +- .../react/reference/functions/usestore.md | 4 +- .../solid/reference/functions/usestore.md | 4 +- .../svelte/reference/functions/shallow.md | 2 +- .../svelte/reference/functions/usestore.md | 4 +- .../vue/reference/functions/shallow.md | 2 +- .../vue/reference/functions/usestore.md | 4 +- docs/reference/classes/derived.md | 236 ++++++++++++++++++ docs/reference/classes/effect.md | 48 ++++ docs/reference/classes/store.md | 124 +++++++++ docs/reference/functions/batch.md | 24 ++ docs/reference/index.md | 34 +++ docs/reference/interfaces/derivedfnprops.md | 50 ++++ docs/reference/interfaces/derivedoptions.md | 92 +++++++ docs/reference/interfaces/storeoptions.md | 96 +++++++ .../type-aliases/unwrapderivedorstore.md | 18 ++ .../variables/depsthathavewrittenthistick.md | 24 ++ docs/reference/variables/derivedtostore.md | 14 ++ docs/reference/variables/storetoderived.md | 28 +++ 20 files changed, 801 insertions(+), 13 deletions(-) create mode 100644 docs/reference/classes/derived.md create mode 100644 docs/reference/classes/effect.md create mode 100644 docs/reference/classes/store.md create mode 100644 docs/reference/functions/batch.md create mode 100644 docs/reference/index.md create mode 100644 docs/reference/interfaces/derivedfnprops.md create mode 100644 docs/reference/interfaces/derivedoptions.md create mode 100644 docs/reference/interfaces/storeoptions.md create mode 100644 docs/reference/type-aliases/unwrapderivedorstore.md create mode 100644 docs/reference/variables/depsthathavewrittenthistick.md create mode 100644 docs/reference/variables/derivedtostore.md create mode 100644 docs/reference/variables/storetoderived.md diff --git a/docs/framework/angular/reference/functions/injectstore.md b/docs/framework/angular/reference/functions/injectstore.md index 872e05bb..2e88b148 100644 --- a/docs/framework/angular/reference/functions/injectstore.md +++ b/docs/framework/angular/reference/functions/injectstore.md @@ -16,7 +16,7 @@ function injectStore( options?): Signal ``` -Defined in: [index.ts:19](https://github.com/TanStack/store/blob/main/packages/angular-store/src/index.ts#L19) +Defined in: [index.ts:19](https://github.com/I-am-abdulazeez/store/blob/main/packages/angular-store/src/index.ts#L19) ### Type Parameters @@ -51,7 +51,7 @@ function injectStore( options?): Signal ``` -Defined in: [index.ts:24](https://github.com/TanStack/store/blob/main/packages/angular-store/src/index.ts#L24) +Defined in: [index.ts:24](https://github.com/I-am-abdulazeez/store/blob/main/packages/angular-store/src/index.ts#L24) ### Type Parameters diff --git a/docs/framework/react/reference/functions/shallow.md b/docs/framework/react/reference/functions/shallow.md index 241360d4..48bdff3b 100644 --- a/docs/framework/react/reference/functions/shallow.md +++ b/docs/framework/react/reference/functions/shallow.md @@ -11,7 +11,7 @@ title: shallow function shallow(objA, objB): boolean ``` -Defined in: [index.ts:34](https://github.com/TanStack/store/blob/main/packages/react-store/src/index.ts#L34) +Defined in: [index.ts:34](https://github.com/I-am-abdulazeez/store/blob/main/packages/react-store/src/index.ts#L34) ## Type Parameters diff --git a/docs/framework/react/reference/functions/usestore.md b/docs/framework/react/reference/functions/usestore.md index 1b1ab558..8de70410 100644 --- a/docs/framework/react/reference/functions/usestore.md +++ b/docs/framework/react/reference/functions/usestore.md @@ -13,7 +13,7 @@ title: useStore function useStore(store, selector?): TSelected ``` -Defined in: [index.ts:11](https://github.com/TanStack/store/blob/main/packages/react-store/src/index.ts#L11) +Defined in: [index.ts:11](https://github.com/I-am-abdulazeez/store/blob/main/packages/react-store/src/index.ts#L11) ### Type Parameters @@ -41,7 +41,7 @@ Defined in: [index.ts:11](https://github.com/TanStack/store/blob/main/packages/r function useStore(store, selector?): TSelected ``` -Defined in: [index.ts:15](https://github.com/TanStack/store/blob/main/packages/react-store/src/index.ts#L15) +Defined in: [index.ts:15](https://github.com/I-am-abdulazeez/store/blob/main/packages/react-store/src/index.ts#L15) ### Type Parameters diff --git a/docs/framework/solid/reference/functions/usestore.md b/docs/framework/solid/reference/functions/usestore.md index c69d28b4..b650c428 100644 --- a/docs/framework/solid/reference/functions/usestore.md +++ b/docs/framework/solid/reference/functions/usestore.md @@ -13,7 +13,7 @@ title: useStore function useStore(store, selector?): Accessor ``` -Defined in: [index.tsx:13](https://github.com/TanStack/store/blob/main/packages/solid-store/src/index.tsx#L13) +Defined in: [index.tsx:13](https://github.com/I-am-abdulazeez/store/blob/main/packages/solid-store/src/index.tsx#L13) ### Type Parameters @@ -41,7 +41,7 @@ Defined in: [index.tsx:13](https://github.com/TanStack/store/blob/main/packages/ function useStore(store, selector?): Accessor ``` -Defined in: [index.tsx:17](https://github.com/TanStack/store/blob/main/packages/solid-store/src/index.tsx#L17) +Defined in: [index.tsx:17](https://github.com/I-am-abdulazeez/store/blob/main/packages/solid-store/src/index.tsx#L17) ### Type Parameters diff --git a/docs/framework/svelte/reference/functions/shallow.md b/docs/framework/svelte/reference/functions/shallow.md index 9ceecfe7..7be5ba1b 100644 --- a/docs/framework/svelte/reference/functions/shallow.md +++ b/docs/framework/svelte/reference/functions/shallow.md @@ -11,7 +11,7 @@ title: shallow function shallow(objA, objB): boolean ``` -Defined in: [index.svelte.ts:43](https://github.com/TanStack/store/blob/main/packages/svelte-store/src/index.svelte.ts#L43) +Defined in: [index.svelte.ts:43](https://github.com/I-am-abdulazeez/store/blob/main/packages/svelte-store/src/index.svelte.ts#L43) ## Type Parameters diff --git a/docs/framework/svelte/reference/functions/usestore.md b/docs/framework/svelte/reference/functions/usestore.md index 1783b5eb..c6e78621 100644 --- a/docs/framework/svelte/reference/functions/usestore.md +++ b/docs/framework/svelte/reference/functions/usestore.md @@ -13,7 +13,7 @@ title: useStore function useStore(store, selector?): object ``` -Defined in: [index.svelte.ts:10](https://github.com/TanStack/store/blob/main/packages/svelte-store/src/index.svelte.ts#L10) +Defined in: [index.svelte.ts:10](https://github.com/I-am-abdulazeez/store/blob/main/packages/svelte-store/src/index.svelte.ts#L10) ### Type Parameters @@ -47,7 +47,7 @@ readonly current: TSelected; function useStore(store, selector?): object ``` -Defined in: [index.svelte.ts:14](https://github.com/TanStack/store/blob/main/packages/svelte-store/src/index.svelte.ts#L14) +Defined in: [index.svelte.ts:14](https://github.com/I-am-abdulazeez/store/blob/main/packages/svelte-store/src/index.svelte.ts#L14) ### Type Parameters diff --git a/docs/framework/vue/reference/functions/shallow.md b/docs/framework/vue/reference/functions/shallow.md index 11cc076d..4d2b2b93 100644 --- a/docs/framework/vue/reference/functions/shallow.md +++ b/docs/framework/vue/reference/functions/shallow.md @@ -11,7 +11,7 @@ title: shallow function shallow(objA, objB): boolean ``` -Defined in: [index.ts:47](https://github.com/TanStack/store/blob/main/packages/vue-store/src/index.ts#L47) +Defined in: [index.ts:47](https://github.com/I-am-abdulazeez/store/blob/main/packages/vue-store/src/index.ts#L47) ## Type Parameters diff --git a/docs/framework/vue/reference/functions/usestore.md b/docs/framework/vue/reference/functions/usestore.md index 59c67731..0ee1bbc0 100644 --- a/docs/framework/vue/reference/functions/usestore.md +++ b/docs/framework/vue/reference/functions/usestore.md @@ -13,7 +13,7 @@ title: useStore function useStore(store, selector?): Readonly> ``` -Defined in: [index.ts:12](https://github.com/TanStack/store/blob/main/packages/vue-store/src/index.ts#L12) +Defined in: [index.ts:12](https://github.com/I-am-abdulazeez/store/blob/main/packages/vue-store/src/index.ts#L12) ### Type Parameters @@ -41,7 +41,7 @@ Defined in: [index.ts:12](https://github.com/TanStack/store/blob/main/packages/v function useStore(store, selector?): Readonly> ``` -Defined in: [index.ts:16](https://github.com/TanStack/store/blob/main/packages/vue-store/src/index.ts#L16) +Defined in: [index.ts:16](https://github.com/I-am-abdulazeez/store/blob/main/packages/vue-store/src/index.ts#L16) ### Type Parameters diff --git a/docs/reference/classes/derived.md b/docs/reference/classes/derived.md new file mode 100644 index 00000000..1f8b1718 --- /dev/null +++ b/docs/reference/classes/derived.md @@ -0,0 +1,236 @@ +--- +id: Derived +title: Derived +--- + + + +# Class: Derived\ + +Defined in: [derived.ts:54](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L54) + +## Type Parameters + +• **TState** + +• **TArr** *extends* `ReadonlyArray`\<[`Derived`](derived.md)\<`any`\> \| [`Store`](store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> + +## Constructors + +### new Derived() + +```ts +new Derived(options): Derived +``` + +Defined in: [derived.ts:92](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L92) + +#### Parameters + +##### options + +[`DerivedOptions`](../interfaces/derivedoptions.md)\<`TState`, `TArr`\> + +#### Returns + +[`Derived`](derived.md)\<`TState`, `TArr`\> + +## Properties + +### lastSeenDepValues + +```ts +lastSeenDepValues: unknown[] = []; +``` + +Defined in: [derived.ts:71](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L71) + +*** + +### listeners + +```ts +listeners: Set>; +``` + +Defined in: [derived.ts:60](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L60) + +*** + +### options + +```ts +options: DerivedOptions; +``` + +Defined in: [derived.ts:63](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L63) + +*** + +### prevState + +```ts +prevState: undefined | TState; +``` + +Defined in: [derived.ts:62](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L62) + +*** + +### state + +```ts +state: TState; +``` + +Defined in: [derived.ts:61](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L61) + +## Methods + +### checkIfRecalculationNeededDeeply() + +```ts +checkIfRecalculationNeededDeeply(): void +``` + +Defined in: [derived.ts:164](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L164) + +#### Returns + +`void` + +*** + +### getDepVals() + +```ts +getDepVals(): object +``` + +Defined in: [derived.ts:77](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L77) + +#### Returns + +`object` + +##### currDepVals + +```ts +currDepVals: unknown[]; +``` + +##### prevDepVals + +```ts +prevDepVals: unknown[]; +``` + +##### prevVal + +```ts +prevVal: undefined | NonNullable; +``` + +*** + +### ~~mount()~~ + +```ts +mount(): () => void +``` + +Defined in: [derived.ts:188](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L188) + +#### Returns + +`Function` + +##### Returns + +`void` + +#### Deprecated + +Use subscribe() instead, which automatically mounts when needed + +*** + +### recompute() + +```ts +recompute(): void +``` + +Defined in: [derived.ts:152](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L152) + +#### Returns + +`void` + +*** + +### registerOnGraph() + +```ts +registerOnGraph(deps): void +``` + +Defined in: [derived.ts:103](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L103) + +#### Parameters + +##### deps + +readonly ( + \| [`Derived`](derived.md)\<`any`, readonly `any`[]\> + \| [`Store`](store.md)\<`any`, (`cb`) => `any`\>)[] = `...` + +#### Returns + +`void` + +*** + +### subscribe() + +```ts +subscribe(listener): () => void +``` + +Defined in: [derived.ts:195](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L195) + +#### Parameters + +##### listener + +`Listener`\<`TState`\> + +#### Returns + +`Function` + +##### Returns + +`void` + +*** + +### unregisterFromGraph() + +```ts +unregisterFromGraph(deps): void +``` + +Defined in: [derived.ts:132](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L132) + +#### Parameters + +##### deps + +readonly ( + \| [`Derived`](derived.md)\<`any`, readonly `any`[]\> + \| [`Store`](store.md)\<`any`, (`cb`) => `any`\>)[] = `...` + +#### Returns + +`void` diff --git a/docs/reference/classes/effect.md b/docs/reference/classes/effect.md new file mode 100644 index 00000000..6722d4fd --- /dev/null +++ b/docs/reference/classes/effect.md @@ -0,0 +1,48 @@ +--- +id: Effect +title: Effect +--- + + + +# Class: Effect + +Defined in: [effect.ts:17](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/effect.ts#L17) + +## Constructors + +### new Effect() + +```ts +new Effect(opts): Effect +``` + +Defined in: [effect.ts:23](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/effect.ts#L23) + +#### Parameters + +##### opts + +`EffectOptions` + +#### Returns + +[`Effect`](effect.md) + +## Methods + +### mount() + +```ts +mount(): () => void +``` + +Defined in: [effect.ts:39](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/effect.ts#L39) + +#### Returns + +`Function` + +##### Returns + +`void` diff --git a/docs/reference/classes/store.md b/docs/reference/classes/store.md new file mode 100644 index 00000000..2f1f934f --- /dev/null +++ b/docs/reference/classes/store.md @@ -0,0 +1,124 @@ +--- +id: Store +title: Store +--- + + + +# Class: Store\ + +Defined in: [store.ts:27](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L27) + +## Type Parameters + +• **TState** + +• **TUpdater** *extends* `AnyUpdater` = (`cb`) => `TState` + +## Constructors + +### new Store() + +```ts +new Store(initialState, options?): Store +``` + +Defined in: [store.ts:36](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L36) + +#### Parameters + +##### initialState + +`TState` + +##### options? + +[`StoreOptions`](../interfaces/storeoptions.md)\<`TState`, `TUpdater`\> + +#### Returns + +[`Store`](store.md)\<`TState`, `TUpdater`\> + +## Properties + +### listeners + +```ts +listeners: Set>; +``` + +Defined in: [store.ts:31](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L31) + +*** + +### options? + +```ts +optional options: StoreOptions; +``` + +Defined in: [store.ts:34](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L34) + +*** + +### prevState + +```ts +prevState: TState; +``` + +Defined in: [store.ts:33](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L33) + +*** + +### state + +```ts +state: TState; +``` + +Defined in: [store.ts:32](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L32) + +## Methods + +### setState() + +```ts +setState(updater): void +``` + +Defined in: [store.ts:51](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L51) + +#### Parameters + +##### updater + +`TUpdater` + +#### Returns + +`void` + +*** + +### subscribe() + +```ts +subscribe(listener): () => void +``` + +Defined in: [store.ts:42](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L42) + +#### Parameters + +##### listener + +`Listener`\<`TState`\> + +#### Returns + +`Function` + +##### Returns + +`void` diff --git a/docs/reference/functions/batch.md b/docs/reference/functions/batch.md new file mode 100644 index 00000000..5e8f6d55 --- /dev/null +++ b/docs/reference/functions/batch.md @@ -0,0 +1,24 @@ +--- +id: batch +title: batch +--- + + + +# Function: batch() + +```ts +function batch(fn): void +``` + +Defined in: [scheduler.ts:140](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/scheduler.ts#L140) + +## Parameters + +### fn + +() => `void` + +## Returns + +`void` diff --git a/docs/reference/index.md b/docs/reference/index.md new file mode 100644 index 00000000..e8ffd4ca --- /dev/null +++ b/docs/reference/index.md @@ -0,0 +1,34 @@ +--- +id: "@tanstack/store" +title: "@tanstack/store" +--- + + + +# @tanstack/store + +## Classes + +- [Derived](classes/derived.md) +- [Effect](classes/effect.md) +- [Store](classes/store.md) + +## Interfaces + +- [DerivedFnProps](interfaces/derivedfnprops.md) +- [DerivedOptions](interfaces/derivedoptions.md) +- [StoreOptions](interfaces/storeoptions.md) + +## Type Aliases + +- [UnwrapDerivedOrStore](type-aliases/unwrapderivedorstore.md) + +## Variables + +- [\_\_depsThatHaveWrittenThisTick](variables/depsthathavewrittenthistick.md) +- [\_\_derivedToStore](variables/derivedtostore.md) +- [\_\_storeToDerived](variables/storetoderived.md) + +## Functions + +- [batch](functions/batch.md) diff --git a/docs/reference/interfaces/derivedfnprops.md b/docs/reference/interfaces/derivedfnprops.md new file mode 100644 index 00000000..0486b28a --- /dev/null +++ b/docs/reference/interfaces/derivedfnprops.md @@ -0,0 +1,50 @@ +--- +id: DerivedFnProps +title: DerivedFnProps +--- + + + +# Interface: DerivedFnProps\ + +Defined in: [derived.ts:23](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L23) + +## Type Parameters + +• **TArr** *extends* `ReadonlyArray`\< + \| [`Derived`](../classes/derived.md)\<`any`\> + \| [`Store`](../classes/store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> + +• **TUnwrappedArr** *extends* `UnwrapReadonlyDerivedOrStoreArray`\<`TArr`\> = `UnwrapReadonlyDerivedOrStoreArray`\<`TArr`\> + +## Properties + +### currDepVals + +```ts +currDepVals: TUnwrappedArr; +``` + +Defined in: [derived.ts:35](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L35) + +*** + +### prevDepVals + +```ts +prevDepVals: undefined | TUnwrappedArr; +``` + +Defined in: [derived.ts:34](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L34) + +*** + +### prevVal + +```ts +prevVal: unknown; +``` + +Defined in: [derived.ts:33](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L33) + +`undefined` if it's the first run diff --git a/docs/reference/interfaces/derivedoptions.md b/docs/reference/interfaces/derivedoptions.md new file mode 100644 index 00000000..90b7b558 --- /dev/null +++ b/docs/reference/interfaces/derivedoptions.md @@ -0,0 +1,92 @@ +--- +id: DerivedOptions +title: DerivedOptions +--- + + + +# Interface: DerivedOptions\ + +Defined in: [derived.ts:38](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L38) + +## Type Parameters + +• **TState** + +• **TArr** *extends* `ReadonlyArray`\< + \| [`Derived`](../classes/derived.md)\<`any`\> + \| [`Store`](../classes/store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> + +## Properties + +### deps + +```ts +deps: TArr; +``` + +Defined in: [derived.ts:47](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L47) + +*** + +### fn() + +```ts +fn: (props) => TState; +``` + +Defined in: [derived.ts:51](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L51) + +Values of the `deps` from before and after the current invocation of `fn` + +#### Parameters + +##### props + +[`DerivedFnProps`](derivedfnprops.md)\<`TArr`\> + +#### Returns + +`TState` + +*** + +### onSubscribe()? + +```ts +optional onSubscribe: (listener, derived) => () => void; +``` + +Defined in: [derived.ts:42](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L42) + +#### Parameters + +##### listener + +`Listener`\<`TState`\> + +##### derived + +[`Derived`](../classes/derived.md)\<`TState`\> + +#### Returns + +`Function` + +##### Returns + +`void` + +*** + +### onUpdate()? + +```ts +optional onUpdate: () => void; +``` + +Defined in: [derived.ts:46](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L46) + +#### Returns + +`void` diff --git a/docs/reference/interfaces/storeoptions.md b/docs/reference/interfaces/storeoptions.md new file mode 100644 index 00000000..a93df2ab --- /dev/null +++ b/docs/reference/interfaces/storeoptions.md @@ -0,0 +1,96 @@ +--- +id: StoreOptions +title: StoreOptions +--- + + + +# Interface: StoreOptions\ + +Defined in: [store.ts:4](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L4) + +## Type Parameters + +• **TState** + +• **TUpdater** *extends* `AnyUpdater` = (`cb`) => `TState` + +## Properties + +### onSubscribe()? + +```ts +optional onSubscribe: (listener, store) => () => void; +``` + +Defined in: [store.ts:17](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L17) + +Called when a listener subscribes to the store. + +#### Parameters + +##### listener + +`Listener`\<`TState`\> + +##### store + +[`Store`](../classes/store.md)\<`TState`, `TUpdater`\> + +#### Returns + +`Function` + +a function to unsubscribe the listener + +##### Returns + +`void` + +*** + +### onUpdate()? + +```ts +optional onUpdate: () => void; +``` + +Defined in: [store.ts:24](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L24) + +Called after the state has been updated, used to derive other state. + +#### Returns + +`void` + +*** + +### updateFn()? + +```ts +optional updateFn: (previous) => (updater) => TState; +``` + +Defined in: [store.ts:11](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/store.ts#L11) + +Replace the default update function with a custom one. + +#### Parameters + +##### previous + +`TState` + +#### Returns + +`Function` + +##### Parameters + +###### updater + +`TUpdater` + +##### Returns + +`TState` diff --git a/docs/reference/type-aliases/unwrapderivedorstore.md b/docs/reference/type-aliases/unwrapderivedorstore.md new file mode 100644 index 00000000..597451b6 --- /dev/null +++ b/docs/reference/type-aliases/unwrapderivedorstore.md @@ -0,0 +1,18 @@ +--- +id: UnwrapDerivedOrStore +title: UnwrapDerivedOrStore +--- + + + +# Type Alias: UnwrapDerivedOrStore\ + +```ts +type UnwrapDerivedOrStore = T extends Derived ? InnerD : T extends Store ? InnerS : never; +``` + +Defined in: [derived.ts:5](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/derived.ts#L5) + +## Type Parameters + +• **T** diff --git a/docs/reference/variables/depsthathavewrittenthistick.md b/docs/reference/variables/depsthathavewrittenthistick.md new file mode 100644 index 00000000..16a8a0f9 --- /dev/null +++ b/docs/reference/variables/depsthathavewrittenthistick.md @@ -0,0 +1,24 @@ +--- +id: __depsThatHaveWrittenThisTick +title: __depsThatHaveWrittenThisTick +--- + + + +# Variable: \_\_depsThatHaveWrittenThisTick + +```ts +const __depsThatHaveWrittenThisTick: object; +``` + +Defined in: [scheduler.ts:28](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/scheduler.ts#L28) + +## Type declaration + +### current + +```ts +current: ( + | Derived + | Store unknown>)[]; +``` diff --git a/docs/reference/variables/derivedtostore.md b/docs/reference/variables/derivedtostore.md new file mode 100644 index 00000000..c317e8bb --- /dev/null +++ b/docs/reference/variables/derivedtostore.md @@ -0,0 +1,14 @@ +--- +id: __derivedToStore +title: __derivedToStore +--- + + + +# Variable: \_\_derivedToStore + +```ts +const __derivedToStore: WeakMap, Set unknown>>>; +``` + +Defined in: [scheduler.ts:23](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/scheduler.ts#L23) diff --git a/docs/reference/variables/storetoderived.md b/docs/reference/variables/storetoderived.md new file mode 100644 index 00000000..38ea09f9 --- /dev/null +++ b/docs/reference/variables/storetoderived.md @@ -0,0 +1,28 @@ +--- +id: __storeToDerived +title: __storeToDerived +--- + + + +# Variable: \_\_storeToDerived + +```ts +const __storeToDerived: WeakMap unknown>, Set>>; +``` + +Defined in: [scheduler.ts:19](https://github.com/I-am-abdulazeez/store/blob/main/packages/store/src/scheduler.ts#L19) + +This is here to solve the pyramid dependency problem where: + A + / \ + B C + \ / + D + +Where we deeply traverse this tree, how do we avoid D being recomputed twice; once when B is updated, once when C is. + +To solve this, we create linkedDeps that allows us to sync avoid writes to the state until all of the deps have been +resolved. + +This is a record of stores, because derived stores are not able to write values to, but stores are