Skip to content

Commit 84dc3eb

Browse files
authored
fix: ensure mutable atoms ignore internal no-arg updates (#289)
* fix: ensure mutable atoms ignore internal no-arg updates * Changeset
1 parent 017f623 commit 84dc3eb

3 files changed

Lines changed: 24 additions & 3 deletions

File tree

.changeset/wet-hairs-lick.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@tanstack/store': patch
3+
---
4+
5+
Fix a regression where mutable atoms could be updated internally with no updater and have their snapshot replaced with `undefined`.
6+
7+
Mutable atoms now ignore internal no-argument `_update()` calls, while computed atoms keep existing recomputation behavior. This prevents external-store state from disappearing during reactive graph cleanup.

packages/store/src/atom.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,15 @@ export function createAtom<T>(
176176
_update(getValue?: T | ((snapshot: T) => T)): boolean {
177177
const prevSub = activeSub
178178
const compare = options?.compare ?? Object.is
179-
activeSub = atom
180-
++cycle
181-
atom.depsTail = undefined
179+
if (isComputed) {
180+
activeSub = atom
181+
++cycle
182+
atom.depsTail = undefined
183+
} else if (getValue === undefined) {
184+
// Mutable atoms can be marked dirty by the reactive graph, but they should
185+
// never be recomputed without an explicit value/updater.
186+
return false
187+
}
182188
if (isComputed) {
183189
atom.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck
184190
}

packages/store/tests/store.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,12 @@ describe('store', () => {
6767
store.setState(() => 24)
6868
expect(fn).toBeCalledWith({ prevVal: 12, currentVal: 24 })
6969
})
70+
71+
test('mutable store should ignore internal no-arg updates', () => {
72+
const store = createStore({ pageIndex: 1 })
73+
const atom = (store as any).atom
74+
75+
expect(atom._update()).toBe(false)
76+
expect(store.state).toEqual({ pageIndex: 1 })
77+
})
7078
})

0 commit comments

Comments
 (0)