Skip to content

Commit

Permalink
Merge branch 'main' into test-async-derived-cached-value-bug
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Oct 23, 2023
2 parents 72cc7a5 + 4cd3564 commit 10ea181
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 11 deletions.
20 changes: 14 additions & 6 deletions src/vanilla/atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,22 @@ export function atom<Value, Args extends unknown[], Result>(
config.read = read as Read<Value, SetAtom<Args, Result>>
} else {
config.init = read
config.read = (get) => get(config)
config.write = ((get: Getter, set: Setter, arg: SetStateAction<Value>) =>
set(
config as unknown as PrimitiveAtom<Value>,
config.read = function (get) {
return get(this)
}
config.write = function (
this: PrimitiveAtom<Value>,
get: Getter,
set: Setter,
arg: SetStateAction<Value>
) {
return set(
this,
typeof arg === 'function'
? (arg as (prev: Value) => Value)(get(config))
? (arg as (prev: Value) => Value)(get(this))
: arg
)) as unknown as Write<Args, Result>
)
} as unknown as Write<Args, Result>
}
if (write) {
config.write = write
Expand Down
14 changes: 11 additions & 3 deletions src/vanilla/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,17 @@ export const createStore = () => {
// Otherwise, check if the dependencies have changed.
// If all dependencies haven't changed, we can use the cache.
if (
Array.from(atomState.d).every(
([a, s]) => a === atom || readAtomState(a) === s
)
Array.from(atomState.d).every(([a, s]) => {
if (a === atom) {
return true
}
const aState = readAtomState(a)
return (
aState === s ||
// We need to check values in case only dependencies are changed
(aState && isEqualAtomValue(aState, s))
)
})
) {
return atomState
}
Expand Down
4 changes: 3 additions & 1 deletion src/vanilla/utils/freezeAtom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export function freezeAtomCreator<
return ((...params: any[]) => {
const anAtom = createAtom(...params)
const origRead = anAtom.read
anAtom.read = (get, options) => deepFreeze(origRead(get, options))
anAtom.read = function (get, options) {
return deepFreeze(origRead.call(this, get, options))
}
return anAtom
}) as CreateAtom
}
3 changes: 2 additions & 1 deletion src/vanilla/utils/unwrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export function unwrap<Value, Args extends unknown[], Result, PendingValue>(
}
return state.f
},
(anAtom as WritableAtom<Value, unknown[], unknown>).write
(_get, set, ...args) =>
set(anAtom as WritableAtom<Value, unknown[], unknown>, ...args)
)
},
anAtom,
Expand Down
12 changes: 12 additions & 0 deletions tests/vanilla/store.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -476,3 +476,15 @@ it('resolves dependencies reliably after a delay (#2192)', async () => {

expect(result).toBe(4) // 3
})

it('should not recompute a derived atom value if unchanged (#2168)', async () => {
const store = createStore()
const countAtom = atom(1)
const derived1Atom = atom((get) => get(countAtom) * 0)
const derive2Fn = vi.fn((get: Getter) => get(derived1Atom))
const derived2Atom = atom(derive2Fn)
expect(store.get(derived2Atom)).toBe(0)
store.set(countAtom, (c) => c + 1)
expect(store.get(derived2Atom)).toBe(0)
expect(derive2Fn).toHaveBeenCalledTimes(1)
})

0 comments on commit 10ea181

Please sign in to comment.