From ffbc4518de7a18156a95dc64de12c6c43e09f1d4 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Sun, 18 May 2025 12:56:18 -0700 Subject: [PATCH 1/2] feat(svelte): allow dynamic Store instance --- packages/svelte-store/src/index.svelte.ts | 21 +++++++++++++------ .../tests/DynamicStore.test.svelte | 15 +++++++++++++ packages/svelte-store/tests/index.test.ts | 9 ++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 packages/svelte-store/tests/DynamicStore.test.svelte diff --git a/packages/svelte-store/src/index.svelte.ts b/packages/svelte-store/src/index.svelte.ts index 3d8429a6..2325f58e 100644 --- a/packages/svelte-store/src/index.svelte.ts +++ b/packages/svelte-store/src/index.svelte.ts @@ -7,23 +7,26 @@ export * from '@tanstack/store' */ export type NoInfer = [T][T extends any ? 0 : never] +type MaybeGetter = T | (() => T) + export function useStore>( - store: Store, + store: MaybeGetter>, selector?: (state: NoInfer) => TSelected, ): { readonly current: TSelected } export function useStore>( - store: Derived, + store: MaybeGetter>, selector?: (state: NoInfer) => TSelected, ): { readonly current: TSelected } export function useStore>( - store: Store | Derived, + store: MaybeGetter> | MaybeGetter>, selector: (state: NoInfer) => TSelected = (d) => d as any, ): { readonly current: TSelected } { - let slice = $state(selector(store.state)) + let slice = $state(selector(toValue(store).state)) $effect(() => { - const unsub = store.subscribe(() => { - const data = selector(store.state) + const actualStore = toValue(store) + const unsub = actualStore.subscribe(() => { + const data = selector(actualStore.state) if (shallow(slice, data)) { return } @@ -40,6 +43,12 @@ export function useStore>( } } +function toValue(store: T | (() => T)): T { + return typeof store === 'function' + ? (store as () => T)() + : store +} + export function shallow(objA: T, objB: T) { if (Object.is(objA, objB)) { return true diff --git a/packages/svelte-store/tests/DynamicStore.test.svelte b/packages/svelte-store/tests/DynamicStore.test.svelte new file mode 100644 index 00000000..a3485964 --- /dev/null +++ b/packages/svelte-store/tests/DynamicStore.test.svelte @@ -0,0 +1,15 @@ + + +

Store: {storeVal.current}

+ diff --git a/packages/svelte-store/tests/index.test.ts b/packages/svelte-store/tests/index.test.ts index b407d268..50f63ab8 100644 --- a/packages/svelte-store/tests/index.test.ts +++ b/packages/svelte-store/tests/index.test.ts @@ -3,6 +3,7 @@ import { render, waitFor } from '@testing-library/svelte' import { userEvent } from '@testing-library/user-event' import { shallow } from '../src/index.svelte.js' import TestBaseStore from './BaseStore.test.svelte' +import DynamicStore from './DynamicStore.test.svelte' import TestRerender from './Render.test.svelte' const user = userEvent.setup() @@ -26,6 +27,14 @@ describe('useStore', () => { await user.click(getByText('Update ignored')) expect(getByText('Number rendered: 2')).toBeInTheDocument() }) + + it('allows us to use a dynamic store', async () => { + const { getByText } = render(DynamicStore) + expect(getByText('Store: 0')).toBeInTheDocument() + + await user.click(getByText('Update store')) + await waitFor(() => expect(getByText('Store: 10')).toBeInTheDocument()) + }) }) describe('shallow', () => { From 826d8bfab515ef418bb9e25409c9255f78f130f9 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 19:57:23 +0000 Subject: [PATCH 2/2] ci: apply automated fixes and generate docs --- docs/framework/svelte/reference/functions/shallow.md | 2 +- docs/framework/svelte/reference/functions/usestore.md | 8 ++++---- packages/svelte-store/src/index.svelte.ts | 4 +--- packages/svelte-store/tests/DynamicStore.test.svelte | 7 +++++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/framework/svelte/reference/functions/shallow.md b/docs/framework/svelte/reference/functions/shallow.md index 9ceecfe7..33a93c92 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:50](https://github.com/TanStack/store/blob/main/packages/svelte-store/src/index.svelte.ts#L50) ## Type Parameters diff --git a/docs/framework/svelte/reference/functions/usestore.md b/docs/framework/svelte/reference/functions/usestore.md index 1783b5eb..3ad55d87 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:12](https://github.com/TanStack/store/blob/main/packages/svelte-store/src/index.svelte.ts#L12) ### Type Parameters @@ -25,7 +25,7 @@ Defined in: [index.svelte.ts:10](https://github.com/TanStack/store/blob/main/pac #### store -`Store`\<`TState`, `any`\> +`MaybeGetter`\<`Store`\<`TState`, `any`\>\> #### selector? @@ -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:16](https://github.com/TanStack/store/blob/main/packages/svelte-store/src/index.svelte.ts#L16) ### Type Parameters @@ -59,7 +59,7 @@ Defined in: [index.svelte.ts:14](https://github.com/TanStack/store/blob/main/pac #### store -`Derived`\<`TState`, `any`\> +`MaybeGetter`\<`Derived`\<`TState`, `any`\>\> #### selector? diff --git a/packages/svelte-store/src/index.svelte.ts b/packages/svelte-store/src/index.svelte.ts index 2325f58e..582994e5 100644 --- a/packages/svelte-store/src/index.svelte.ts +++ b/packages/svelte-store/src/index.svelte.ts @@ -44,9 +44,7 @@ export function useStore>( } function toValue(store: T | (() => T)): T { - return typeof store === 'function' - ? (store as () => T)() - : store + return typeof store === 'function' ? (store as () => T)() : store } export function shallow(objA: T, objB: T) { diff --git a/packages/svelte-store/tests/DynamicStore.test.svelte b/packages/svelte-store/tests/DynamicStore.test.svelte index a3485964..2a37fb72 100644 --- a/packages/svelte-store/tests/DynamicStore.test.svelte +++ b/packages/svelte-store/tests/DynamicStore.test.svelte @@ -8,8 +8,11 @@ let store = $state(createStore(0)) - const storeVal = useStore(() => store, (state) => state.count) + const storeVal = useStore( + () => store, + (state) => state.count, + )

Store: {storeVal.current}

- +