feat: add cleanup function to effects

This commit is contained in:
Richard 2024-06-01 18:44:23 -07:00
parent fefcf39283
commit 5fd064e70a
2 changed files with 41 additions and 5 deletions

View file

@ -24,7 +24,23 @@ return function()
unsubscribe() unsubscribe()
a(4) a(4)
expect(current).to.equal(6) expect(current).to.equal(6)
end) end)
it("accepts a cleanup function", function()
local a = atom(0)
local cleanups = 0
local unsubscribe = effect(function()
a()
return function()
cleanups += 1
end
end)
expect(cleanups).to.equal(0)
a(1)
expect(cleanups).to.equal(1)
unsubscribe()
expect(cleanups).to.equal(2)
end)
end end

View file

@ -1,10 +1,26 @@
local store = require(script.Parent.store) local store = require(script.Parent.store)
local function effect(molecule: () -> nil): () -> () type Cleanup = () -> ()
local captured = store.capture(molecule)
--[=[
Runs the given callback immediately and whenever any atom it depends on
changes. Returns a cleanup function that unsubscribes the callback.
Note that dependencies are only evaluated once when the effect is created,
and conditional dependencies may not work as expected.
@param callback The function to run.
@return A function that unsubscribes the callback.
]=]
local function effect(callback: () -> any): () -> ()
local captured, cleanup = store.capture(callback)
local function listener() local function listener()
molecule() if cleanup then
cleanup()
end
cleanup = callback()
end end
for atom in captured do for atom in captured do
@ -15,7 +31,11 @@ local function effect(molecule: () -> nil): () -> ()
for atom in captured do for atom in captured do
store.listeners[atom][listener] = nil store.listeners[atom][listener] = nil
end end
if cleanup then
cleanup()
end
end end
end end
return effect return effect :: (callback: (() -> ()) | (() -> Cleanup)) -> Cleanup