mirror of
https://github.com/littensy/charm.git
synced 2026-10-22 12:41:37 +00:00
fix: add unmount behavior to split atoms
This commit is contained in:
parent
4586882d3c
commit
fc3cd6d9ad
4 changed files with 25 additions and 16 deletions
|
|
@ -125,4 +125,12 @@ return function()
|
||||||
expect(updated).to.equal(1)
|
expect(updated).to.equal(1)
|
||||||
expect(deleted).to.equal(3)
|
expect(deleted).to.equal(3)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("unmounts from parent atom", function()
|
||||||
|
local itemsAtom = atom({})
|
||||||
|
local itemAtoms = split(itemsAtom)
|
||||||
|
expect((next(itemsAtom.listeners))).to.be.ok()
|
||||||
|
itemAtoms:unmount()
|
||||||
|
expect((next(itemsAtom.listeners))).to.never.be.ok()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -33,16 +33,11 @@ local atomCount = 0
|
||||||
local function atom<State>(state: State): Atom<State>
|
local function atom<State>(state: State): Atom<State>
|
||||||
atomCount += 1
|
atomCount += 1
|
||||||
|
|
||||||
local listeners: { [(State) -> ()]: true } = {}
|
|
||||||
local label = `atom{atomCount}`
|
|
||||||
local traceback = debug.traceback(nil, 2)
|
|
||||||
local owners: { [any]: true } = {}
|
|
||||||
|
|
||||||
local atom = {
|
local atom = {
|
||||||
listeners = listeners,
|
listeners = {},
|
||||||
debugTraceback = traceback,
|
debugTraceback = debug.traceback(nil, 2),
|
||||||
debugLabel = label,
|
debugLabel = `atom{atomCount}`,
|
||||||
owners = owners,
|
owners = {},
|
||||||
} :: Atom<State>
|
} :: Atom<State>
|
||||||
|
|
||||||
local equals: ((State, State) -> boolean)?
|
local equals: ((State, State) -> boolean)?
|
||||||
|
|
@ -68,7 +63,7 @@ local function atom<State>(state: State): Atom<State>
|
||||||
if not (if equals then equals(state, nextState) else state == nextState) then
|
if not (if equals then equals(state, nextState) else state == nextState) then
|
||||||
state = nextState
|
state = nextState
|
||||||
|
|
||||||
for listener in table.clone(listeners) do
|
for listener in table.clone(self.listeners) do
|
||||||
listener(state)
|
listener(state)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -80,7 +75,7 @@ local function atom<State>(state: State): Atom<State>
|
||||||
if not (if equals then equals(state, nextState) else state == nextState) then
|
if not (if equals then equals(state, nextState) else state == nextState) then
|
||||||
state = nextState
|
state = nextState
|
||||||
|
|
||||||
for listener in table.clone(listeners) do
|
for listener in table.clone(self.listeners) do
|
||||||
listener(state)
|
listener(state)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -99,20 +94,20 @@ local function atom<State>(state: State): Atom<State>
|
||||||
function atom:readonly(): ReadonlyAtom<State>
|
function atom:readonly(): ReadonlyAtom<State>
|
||||||
function setter(_, _)
|
function setter(_, _)
|
||||||
if _G.__DEV__ then
|
if _G.__DEV__ then
|
||||||
error(`Attempt to set read-only atom '{label}' created at: {traceback}`, 3)
|
error(`Attempt to set read-only atom '{self.debugLabel}' created at: {self.debugTraceback}`, 3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function atom:named(name: string): Atom<State>
|
function atom:named(name: string): Atom<State>
|
||||||
label = name
|
self.debugLabel = name
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function atom:unmount()
|
function atom:unmount()
|
||||||
table.clear(listeners)
|
table.clear(self.listeners)
|
||||||
table.clear(owners)
|
table.clear(self.owners)
|
||||||
reference.release(self)
|
reference.release(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ local function derive<Result>(...): ReadonlyAtom<Result>
|
||||||
local getDerivedAtom = reference.weak(derivedAtom)
|
local getDerivedAtom = reference.weak(derivedAtom)
|
||||||
|
|
||||||
function derivedAtom:unmount()
|
function derivedAtom:unmount()
|
||||||
derivedAtomUnmount(self)
|
derivedAtomUnmount(derivedAtom)
|
||||||
|
|
||||||
for listener in listeners do
|
for listener in listeners do
|
||||||
for _, atom in atoms do
|
for _, atom in atoms do
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ local function split<Item, Key>(
|
||||||
keyExtractor: ((Item) -> Key)?
|
keyExtractor: ((Item) -> Key)?
|
||||||
): ReadonlyAtom<{ [Key]: Atom<Item> }>
|
): ReadonlyAtom<{ [Key]: Atom<Item> }>
|
||||||
local splitAtom: ReadonlyAtom<{ [Key]: Atom<Item> }> = atom({}):readonly()
|
local splitAtom: ReadonlyAtom<{ [Key]: Atom<Item> }> = atom({}):readonly()
|
||||||
|
local splitAtomUnmount = splitAtom.unmount
|
||||||
local getSplitAtom = reference.weak(splitAtom)
|
local getSplitAtom = reference.weak(splitAtom)
|
||||||
|
|
||||||
local previousAtoms: { [Key]: Atom<Item> } = {}
|
local previousAtoms: { [Key]: Atom<Item> } = {}
|
||||||
|
|
@ -67,6 +68,11 @@ local function split<Item, Key>(
|
||||||
splitAtom:setForced(atoms)
|
splitAtom:setForced(atoms)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function splitAtom:unmount()
|
||||||
|
splitAtomUnmount(splitAtom)
|
||||||
|
cleanup()
|
||||||
|
end
|
||||||
|
|
||||||
itemsAtom.listeners[listener] = true
|
itemsAtom.listeners[listener] = true
|
||||||
listener(itemsAtom:get())
|
listener(itemsAtom:get())
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue