diff --git a/docs/framework/preact/reference/functions/shallow.md b/docs/framework/preact/reference/functions/shallow.md index 62f1aa9..8284cca 100644 --- a/docs/framework/preact/reference/functions/shallow.md +++ b/docs/framework/preact/reference/functions/shallow.md @@ -9,7 +9,7 @@ title: shallow function shallow(objA, objB): boolean; ``` -Defined in: [index.ts:67](https://github.com/TanStack/store/blob/main/packages/preact-store/src/index.ts#L67) +Defined in: [index.ts:130](https://github.com/TanStack/store/blob/main/packages/preact-store/src/index.ts#L130) ## Type Parameters diff --git a/docs/framework/preact/reference/functions/useStore.md b/docs/framework/preact/reference/functions/useStore.md index 1cc5546..22d4ed5 100644 --- a/docs/framework/preact/reference/functions/useStore.md +++ b/docs/framework/preact/reference/functions/useStore.md @@ -14,7 +14,7 @@ function useStore( options?): TSelected; ``` -Defined in: [index.ts:41](https://github.com/TanStack/store/blob/main/packages/preact-store/src/index.ts#L41) +Defined in: [index.ts:104](https://github.com/TanStack/store/blob/main/packages/preact-store/src/index.ts#L104) ### Type Parameters @@ -53,7 +53,7 @@ function useStore( options?): TSelected; ``` -Defined in: [index.ts:46](https://github.com/TanStack/store/blob/main/packages/preact-store/src/index.ts#L46) +Defined in: [index.ts:109](https://github.com/TanStack/store/blob/main/packages/preact-store/src/index.ts#L109) ### Type Parameters diff --git a/packages/preact-store/src/index.ts b/packages/preact-store/src/index.ts index 5461ae8..7b2c5bc 100644 --- a/packages/preact-store/src/index.ts +++ b/packages/preact-store/src/index.ts @@ -1,9 +1,72 @@ -import { useSyncExternalStore } from 'preact/compat' -import { useRef } from 'preact/hooks' +import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks' import type { Derived, Store } from '@tanstack/store' export * from '@tanstack/store' +type InternalStore = { + _value: any + _getSnapshot: () => any +} + +type StoreRef = { + _instance: InternalStore +} + +/** + * This is taken from https://github.com/preactjs/preact/blob/main/compat/src/hooks.js#L8-L54 + * which is taken from https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L84 + * on a high level this cuts out the warnings, ... and attempts a smaller implementation. + * This way we don't have to import preact/compat with side effects + */ +function useSyncExternalStore( + subscribe: (onStoreChange: () => void) => () => void, + getSnapshot: () => any, +) { + const value = getSnapshot() + + const [{ _instance }, forceUpdate] = useState({ + _instance: { _value: value, _getSnapshot: getSnapshot }, + }) + + useLayoutEffect(() => { + _instance._value = value + _instance._getSnapshot = getSnapshot + + if (didSnapshotChange(_instance)) { + forceUpdate({ _instance }) + } + }, [subscribe, value, getSnapshot]) + + useEffect(() => { + if (didSnapshotChange(_instance)) { + forceUpdate({ _instance }) + } + + return subscribe(() => { + if (didSnapshotChange(_instance)) { + forceUpdate({ _instance }) + } + }) + }, [subscribe]) + + return value +} + +function didSnapshotChange(inst: { + _getSnapshot: () => any + _value: any +}): boolean { + const latestGetSnapshot = inst._getSnapshot + const prevValue = inst._value + try { + const nextValue = latestGetSnapshot() + return !Object.is(prevValue, nextValue) + // eslint-disable-next-line no-unused-vars + } catch (_error) { + return true + } +} + /** * @private */ @@ -120,5 +183,3 @@ function getOwnKeys(obj: object): Array { Object.getOwnPropertySymbols(obj), ) } - -// force