Skip to content

Commit cdde1b8

Browse files
authored
fix: subscribing withAtomEffect gives stale value (#80)
* fix: subscribing withAtomEffect gives stale value * update version to 2.1.5
1 parent abf153e commit cdde1b8

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "jotai-effect",
33
"description": "👻🔁",
4-
"version": "2.1.4",
4+
"version": "2.1.5",
55
"type": "module",
66
"author": "David Maskasky",
77
"contributors": [

src/withAtomEffect.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export function withAtomEffect<T extends Atom<unknown>>(
4343
const ensureAtomState = buildingBlocks[11]
4444
const flushCallbacks = buildingBlocks[12]
4545
const readAtomState = buildingBlocks[14]
46+
const invalidateDependents = buildingBlocks[15]
4647
const mountDependencies = buildingBlocks[17]
4748
const mountAtom = buildingBlocks[18]
4849
const unmountAtom = buildingBlocks[19]
@@ -95,8 +96,16 @@ export function withAtomEffect<T extends Atom<unknown>>(
9596
}
9697
})
9798
storeHooks.m.add(targetWithEffect, function mountEffect() {
99+
const atomState = ensureAtomState(store, targetWithEffect)
100+
const { n } = atomState
98101
mountAtom(store, effectAtom)
99102
flushCallbacks(store)
103+
if (n !== atomState.n) {
104+
const unsub = storeHooks.f.add(() => {
105+
invalidateDependents(store, targetWithEffect)
106+
unsub()
107+
})
108+
}
100109
})
101110
storeHooks.u.add(targetWithEffect, function unmountEffect() {
102111
unmountAtom(store, effectAtom)

tests/withAtomEffect.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,4 +394,33 @@ describe('withAtomEffect', () => {
394394
u1()
395395
u2()
396396
})
397+
398+
it('subscribing to an enhanced atom after it has been written to does not cause a stale read', () => {
399+
const atomA = atom<boolean>()
400+
atomA.debugLabel = 'atomA'
401+
const atomB = withAtomEffect(atom(false), (get, set) => {
402+
if (get(atomA) === true) {
403+
set(atomB, true)
404+
}
405+
})
406+
atomB.debugLabel = 'atomB'
407+
const atomC = atom((get) => get(atomB))
408+
atomC.debugLabel = 'atomC'
409+
410+
const store = createDebugStore()
411+
expect(store.get(atomA)).toBe(undefined)
412+
expect(store.get(atomB)).toBe(false)
413+
expect(store.get(atomC)).toBe(false)
414+
415+
store.set(atomA, true)
416+
expect(store.get(atomA)).toBe(true)
417+
expect(store.get(atomB)).toBe(false)
418+
expect(store.get(atomC)).toBe(false)
419+
420+
store.sub(atomC, () => {})
421+
expect(store.get(atomA)).toBe(true)
422+
expect(store.get(atomB)).toBe(true)
423+
424+
expect(store.get(atomC)).toBe(true)
425+
})
397426
})

0 commit comments

Comments
 (0)