Skip to content

Commit

Permalink
notify on change if state changed before subscription (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alqanar authored Dec 18, 2024
1 parent 00f51f6 commit 49249cc
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 8 deletions.
15 changes: 8 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"index.js": "{ useStore }",
"nanostores": "{ map, computed }"
},
"limit": "901 B"
"limit": "914 B"
}
]
}
16 changes: 16 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})

0 comments on commit 49249cc

Please sign in to comment.