Skip to content

Commit

Permalink
fix: should update dependents with the value of the unwrapped atom wh…
Browse files Browse the repository at this point in the history
…en the promise resolves (#2936)

* test: should update dependents with the value of the unwrapped atom when the promise resolves

* handle mounting and unmounting of sync and async dependencies separately

* add failing tests

* drop store changes

* alternate fix

* follow store refactor

---------

Co-authored-by: daishi <[email protected]>
Co-authored-by: Daishi Kato <[email protected]>
  • Loading branch information
3 people authored Jan 20, 2025
1 parent 2348ff6 commit 3c51426
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/vanilla/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
const mountDependenciesIfAsync = () => {
if (atomState.m) {
mountDependencies(atom, atomState)
recomputeInvalidatedAtoms()
flushCallbacks()
}
}
Expand Down Expand Up @@ -569,11 +570,17 @@ const buildStore = (...storeArgs: StoreArgs): Store => {

const mountDependencies = (atom: AnyAtom, atomState: AtomState) => {
if (atomState.m && !isPendingPromise(atomState.v)) {
for (const a of atomState.d.keys()) {
for (const [a, n] of atomState.d) {
if (!atomState.m.d.has(a)) {
const aMounted = mountAtom(a, ensureAtomState(a))
const aState = ensureAtomState(a)
const aMounted = mountAtom(a, aState)
aMounted.t.add(atom)
atomState.m.d.add(a)
if (n !== aState.n) {
changedAtoms.set(a, aState)
aState.u?.()
invalidateDependents(aState)
}
}
}
for (const a of atomState.m.d || []) {
Expand Down
14 changes: 14 additions & 0 deletions tests/vanilla/utils/unwrap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,17 @@ describe('unwrap', () => {
expect(store.get(syncAtom)).toEqual('concrete')
})
})

it('should update dependents with the value of the unwrapped atom when the promise resolves', async () => {
const store = createStore()
const asyncTarget = atom(() => Promise.resolve('value'))
const target = unwrap(asyncTarget)
const results: string[] = []
const derived = atom(async (get) => {
await Promise.resolve()
results.push('effect ' + get(target))
})
store.sub(derived, () => {})
await new Promise((r) => setTimeout(r))
expect(results).toEqual(['effect undefined', 'effect value'])
})

0 comments on commit 3c51426

Please sign in to comment.