mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
fix: do not track implicit dependencies in observe() and mapped() (#39)
* fix: use `subscribe` for explicit dependencies * fix: call listeners initially once * fix: wrap initial run in `peek()`
This commit is contained in:
parent
a430cf63e5
commit
6be2fbb746
2 changed files with 22 additions and 12 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
local atom = require(script.Parent.atom)
|
local atom = require(script.Parent.atom)
|
||||||
local effect = require(script.Parent.effect)
|
|
||||||
local store = require(script.Parent.store)
|
local store = require(script.Parent.store)
|
||||||
|
local subscribe = require(script.Parent.subscribe)
|
||||||
local types = require(script.Parent.types)
|
local types = require(script.Parent.types)
|
||||||
type Atom<T> = types.Atom<T>
|
type Atom<T> = types.Atom<T>
|
||||||
type Selector<T> = types.Selector<T>
|
type Selector<T> = types.Selector<T>
|
||||||
|
|
@ -26,13 +26,14 @@ local function mapped<K0, V0, K1, V1>(callback: Selector<{ [K0]: V0 }>, mapper:
|
||||||
local prevMappedItems: { [K1]: V1 } = {}
|
local prevMappedItems: { [K1]: V1 } = {}
|
||||||
local unsubscribe
|
local unsubscribe
|
||||||
|
|
||||||
unsubscribe = effect(function()
|
local function listener(items: { [K0]: V0 })
|
||||||
if not mappedAtomRef.current then
|
local mappedAtom = mappedAtomRef.current
|
||||||
|
|
||||||
|
if not mappedAtom then
|
||||||
return unsubscribe()
|
return unsubscribe()
|
||||||
end
|
end
|
||||||
|
|
||||||
local items = callback()
|
local mappedItems = table.clone(mappedAtom())
|
||||||
local mappedItems = table.clone(store.peek(mappedAtomRef.current))
|
|
||||||
local mappedKeys = {}
|
local mappedKeys = {}
|
||||||
|
|
||||||
-- TODO: Only call mapper if the item has changed.
|
-- TODO: Only call mapper if the item has changed.
|
||||||
|
|
@ -56,6 +57,12 @@ local function mapped<K0, V0, K1, V1>(callback: Selector<{ [K0]: V0 }>, mapper:
|
||||||
|
|
||||||
prevMappedItems = mappedItems
|
prevMappedItems = mappedItems
|
||||||
mappedAtom(mappedItems)
|
mappedAtom(mappedItems)
|
||||||
|
end
|
||||||
|
|
||||||
|
unsubscribe = subscribe(callback, listener)
|
||||||
|
|
||||||
|
store.peek(function(): ()
|
||||||
|
listener(callback())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return mappedAtom
|
return mappedAtom
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
local effect = require(script.Parent.effect)
|
local store = require(script.Parent.store)
|
||||||
|
local subscribe = require(script.Parent.subscribe)
|
||||||
local types = require(script.Parent.types)
|
local types = require(script.Parent.types)
|
||||||
type Selector<T> = types.Selector<T>
|
type Selector<T> = types.Selector<T>
|
||||||
|
|
||||||
|
|
@ -16,9 +17,7 @@ local function noop() end
|
||||||
local function observe<K, V>(callback: Selector<{ [K]: V }>, factory: (value: V, key: K) -> (() -> ())?): () -> ()
|
local function observe<K, V>(callback: Selector<{ [K]: V }>, factory: (value: V, key: K) -> (() -> ())?): () -> ()
|
||||||
local connections: { [K]: () -> () } = {}
|
local connections: { [K]: () -> () } = {}
|
||||||
|
|
||||||
local unsubscribe = effect(function()
|
local function listener(state: { [K]: V })
|
||||||
local state = callback()
|
|
||||||
|
|
||||||
for key, disconnect in next, connections do
|
for key, disconnect in next, connections do
|
||||||
if state[key] == nil then
|
if state[key] == nil then
|
||||||
connections[key] = nil
|
connections[key] = nil
|
||||||
|
|
@ -31,17 +30,21 @@ local function observe<K, V>(callback: Selector<{ [K]: V }>, factory: (value: V,
|
||||||
connections[key] = factory(value, key) or noop
|
connections[key] = factory(value, key) or noop
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local unsubscribe = subscribe(callback, listener)
|
||||||
|
|
||||||
|
store.peek(function(): ()
|
||||||
|
listener(callback())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local function cleanup()
|
return function()
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
for _, disconnect in next, connections do
|
for _, disconnect in next, connections do
|
||||||
disconnect()
|
disconnect()
|
||||||
end
|
end
|
||||||
table.clear(connections)
|
table.clear(connections)
|
||||||
end
|
end
|
||||||
|
|
||||||
return cleanup
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return observe
|
return observe
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue