diff --git a/index.js b/index.js index de565de..e25c1f0 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ import { listenKeys } from 'nanostores' import { useCallback, useRef, useSyncExternalStore } from 'react' let emit = (snapshotRef, onChange) => value => { + if (snapshotRef.current === value) return snapshotRef.current = value onChange() } @@ -10,13 +11,13 @@ export function useStore(store, { keys, deps = [store, keys] } = {}) { let snapshotRef = useRef() snapshotRef.current = store.get() - let subscribe = useCallback( - onChange => - keys?.length > 0 - ? listenKeys(store, keys, emit(snapshotRef, onChange)) - : store.listen(emit(snapshotRef, onChange)), - deps - ) + let subscribe = useCallback(onChange => { + emit(snapshotRef, onChange)(store.value) + + return keys?.length > 0 + ? listenKeys(store, keys, emit(snapshotRef, onChange)) + : store.listen(emit(snapshotRef, onChange)) + }, deps) let get = () => snapshotRef.current return useSyncExternalStore(subscribe, get, get) diff --git a/package.json b/package.json index 344c3b3..1433bdf 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "index.js": "{ useStore }", "nanostores": "{ map, computed }" }, - "limit": "901 B" + "limit": "914 B" } ] } diff --git a/test/index.test.ts b/test/index.test.ts index ba3a502..f21dd7c 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -226,3 +226,19 @@ test('works with stores that set their values in lifecycle hooks', async () => { render(h(Test)) }) + +test('useSyncExternalStore late subscription handling', async () => { + let $1 = atom('original content') + + let Test: FC = () => { + let value = useStore($1) + // state update before the useSyncExternalStore subsciption happen + $1.set('updated content') + + return h('div', { 'data-testid': 'subscription-test' }, value) + } + + render(h(Test)) + + equal(screen.getByTestId('subscription-test').textContent, 'updated content') +})