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 3d8429a6..582994e5 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,10 @@ 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..2a37fb72 --- /dev/null +++ b/packages/svelte-store/tests/DynamicStore.test.svelte @@ -0,0 +1,18 @@ + + +

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', () => {