Skip to content

Commit

Permalink
fix: call listener when setAtom changes value of atom on mount and un…
Browse files Browse the repository at this point in the history
…mount
  • Loading branch information
dmaskasky committed Nov 12, 2024
1 parent 1b5601a commit 687380e
Showing 1 changed file with 23 additions and 6 deletions.
29 changes: 23 additions & 6 deletions src/vanilla/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ const addDependency = <Value>(
type Pending = readonly [
dependents: Map<AnyAtom, Set<AnyAtom>>,
atomStates: Map<AnyAtom, AtomState>,
functions: Set<() => void>,
functions: Set<(pending: Pending) => void>,
]

const createPending = (): Pending => [new Map(), new Map(), new Set()]
Expand Down Expand Up @@ -194,7 +194,10 @@ const addPendingDependent = (
const getPendingDependents = (pending: Pending, atom: AnyAtom) =>
pending[0].get(atom)

const addPendingFunction = (pending: Pending, fn: () => void) => {
const addPendingFunction = (
pending: Pending,
fn: (pending: Pending) => void,
) => {
pending[2].add(fn)
}

Expand All @@ -206,7 +209,7 @@ const flushPending = (pending: Pending) => {
const functions = new Set(pending[2])
pending[2].clear()
atomStates.forEach((atomState) => atomState.m?.l.forEach((l) => l()))
functions.forEach((fn) => fn())
functions.forEach((fn) => fn(pending))
}
}

Expand Down Expand Up @@ -574,7 +577,7 @@ const buildStore = (
}
if (isActuallyWritableAtom(atom)) {
const mounted = atomState.m
addPendingFunction(pending, () => {
addPendingFunction(pending, (pending) => {
const onUnmount = atomOnMount(atom, (...args) =>
writeAtomState(pending, atom, ...args),
)
Expand Down Expand Up @@ -620,13 +623,27 @@ const buildStore = (
const pending = createPending()
const atomState = getAtomState(atom)
const mounted = mountAtom(pending, atom, atomState)
flushPending(pending)
const listeners = mounted.l
listeners.add(listener)
flushPending(pending)
return () => {
listeners.delete(listener)
const pending = createPending()
unmountAtom(pending, atom, atomState)
const isMounted = !!unmountAtom(pending, atom, atomState)
const hasPrevValue = 'v' in atomState
const prevValue = atomState.v
if (!isMounted) {
addPendingFunction(pending, () => {
if (
!atomState.m &&
!isPendingPromise(atomState.v) &&
(!hasPrevValue || !Object.is(prevValue, atomState.v))
) {
// call listener when setAtom changes value of atom on unmount
listener()
}
})
}
flushPending(pending)
}
}
Expand Down

0 comments on commit 687380e

Please sign in to comment.