Feat: Add dispose
method to van.derive
for explicit cleanup of derived states
#441
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem Description
Currently,
van.js
'sderive
function creates reactive states that listen to their dependencies. Whilevan.js
has a garbage collection mechanism tied to DOM element connectivity, derived states that are not directly associated with a DOM element (or are associated with the globalalwaysConnectedDom
object) are never garbage collected. This is particularly problematic whenvan.derive
is used to implement higher-level reactive primitives, such aswatch
orwatchEffect
in Vue-like adapters, where watchers need to be explicitly stopped during their lifecycle.Without an explicit way to stop these derivations, listeners can accumulate, leading to potential memory leaks and incorrect behavior when a watcher is expected to cease its activity.
Proposed Solution
This pull request introduces an explicit
dispose()
method to the state object returned byvan.derive()
.The
derive
function has been modified as follows:listener
object created for the derivation and thesourceStates
(dependencies) that the derived function reads from.dispose()
method is attached to the state objects
returned byvan.derive()
.s.dispose()
is called:sourceStates
.sourceState
, it removes the specificlistener
associated with thisderive
call from thatsourceState
's internal_listeners
array.sourceStates
and the originallistener
's function and state to aid garbage collection and makes subsequent calls todispose()
a no-op.This provides a clean and explicit mechanism for consumers of
van.derive()
to manually stop a derived state from listening to its dependencies, effectively cleaning up the reactive effect.Benefits
watch
,watchEffect
) on top ofvan.js
, allowing these abstractions to correctly stop their underlying reactive effects.van.derive()
.Code Changes
The primary modification is within the
derive
function invan.js
to:dispose
method to the returned state object, which uses this tracking to remove the listener.Example Usage (Conceptual)
This change makes
van.js
more robust and flexible for a wider range of use cases, especially when integrating with or building other reactive systems.