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'sderivefunction creates reactive states that listen to their dependencies. Whilevan.jshas 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 globalalwaysConnectedDomobject) are never garbage collected. This is particularly problematic whenvan.deriveis used to implement higher-level reactive primitives, such aswatchorwatchEffectin 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
derivefunction has been modified as follows:listenerobject created for the derivation and thesourceStates(dependencies) that the derived function reads from.dispose()method is attached to the state objectsreturned byvan.derive().s.dispose()is called:sourceStates.sourceState, it removes the specificlistenerassociated with thisderivecall from thatsourceState's internal_listenersarray.sourceStatesand 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
derivefunction invan.jsto:disposemethod to the returned state object, which uses this tracking to remove the listener.Example Usage (Conceptual)
This change makes
van.jsmore robust and flexible for a wider range of use cases, especially when integrating with or building other reactive systems.