feat: allow factory to return nil

This commit is contained in:
Richard 2024-07-10 15:08:50 -07:00
parent 1ea601a2fc
commit ce5ae96c2b

View file

@ -2,6 +2,8 @@ local effect = require(script.Parent.effect)
local types = require(script.Parent.types) local types = require(script.Parent.types)
type Molecule<T> = types.Molecule<T> type Molecule<T> = types.Molecule<T>
local function noop() end
--[=[ --[=[
Creates an instance of `factory` for each item in the atom's state, and Creates an instance of `factory` for each item in the atom's state, and
cleans up the instance when the item is removed. Returns a cleanup function cleans up the instance when the item is removed. Returns a cleanup function
@ -11,34 +13,38 @@ type Molecule<T> = types.Molecule<T>
@param factory The function that tracks the lifecycle of each item. @param factory The function that tracks the lifecycle of each item.
@return A function that unsubscribes all instances. @return A function that unsubscribes all instances.
]=] ]=]
local function observe<K, V>(molecule: Molecule<{ [K]: V }>, factory: (value: V, key: K) -> () -> ()): () -> () local function observe<K, V>(molecule: Molecule<{ [K]: V }>, factory: (value: V, key: K) -> (() -> ())?): () -> ()
local connections: { [K]: () -> () } = {} local connections: { [K]: () -> () } = {}
local unsubscribe = effect(function() local unsubscribe = effect(function()
local state = molecule() local state = molecule()
for key, disconnect in 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
disconnect() disconnect()
end end
end end
for key, value in state do for key, value in next, state do
if not connections[key] then if not connections[key] then
connections[key] = factory(value, key) connections[key] = factory(value, key) or noop
end end
end end
end) end)
local function cleanup() local function cleanup()
unsubscribe() unsubscribe()
for _, disconnect in connections do for _, disconnect in next, connections do
disconnect() disconnect()
end end
table.clear(connections)
end end
return cleanup return cleanup
end end
return observe return observe :: <K, V>(
molecule: Molecule<{ [K]: V }>,
factory: ((value: V, key: K) -> () -> ()) | (value: V, key: K) -> ()
) -> () -> ()