Comments (2)
I agree, this seems like it would do the ticket. It is a significant breaking change too however — which will probably be required anyway whenever I get around to implementing something like this. There are a number of refactors that have been worked on that havent yet seen the light of day, but as soon as I get more time to tackle this unwatch will be a high priority!
from arrow-js.
Hey @justin-schroeder !
Had some time today so played around with ways to add in a cleanup reference for watch
. Appreciate any feedback you may have.
I believe this edit to the reactive.ts file would allow cleaning up a watch function as needed:
- https://github.com/justin-schroeder/arrow-js/blob/master/src/reactive.ts
- Function
w
- Proposed Edit is adding in the
unwatch
method.
/**
* Watch a function and track any reactive dependencies on it, re-calling it if
* those dependencies are changed. Returns a function to unwatch.
* @param {CallableFunction} fn
* @param {CallableFunction} after?
* @returns [unknown, () => void]
*/
export function w<
T extends (...args: any[]) => unknown,
F extends (...args: any[]) => any | undefined
>(fn: T, after?: F): [F extends undefined ? ReturnType<T> : ReturnType<F>, () => void] {
const trackingId = Symbol()
// Ensure a new dependency tracker for this watch instance
if (!dependencyCollector.has(trackingId)) {
dependencyCollector.set(trackingId, new Map())
}
let currentDeps: Map<ReactiveProxy<DataSource>, Set<DataSourceKey>> = new Map()
const queuedCallFn = queue(callFn)
function callFn() {
// Reset dependencies for this call
dependencyCollector.set(trackingId, new Map())
const value: unknown = fn()
const newDeps = dependencyCollector.get(trackingId) as Map<ReactiveProxy<DataSource>, Set<DataSourceKey>>
// Clean up after getting the new dependencies
dependencyCollector.delete(trackingId)
// Remove old observers
currentDeps.forEach((propertiesToUnobserve, proxy) => {
propertiesToUnobserve.forEach((prop) => proxy.$off(prop, queuedCallFn))
})
// Add new observers
newDeps.forEach((properties, proxy) => {
properties.forEach((prop) => proxy.$on(prop, queuedCallFn))
})
// Update the current dependencies
currentDeps = newDeps
return after ? after(value) : value
}
// Setup initial call and observers
const result = callFn()
// Setup unwatchfunction
function unwatch() {
// Remove all observers set by this watch
currentDeps.forEach((propertiesToUnobserve, proxy) => {
propertiesToUnobserve.forEach((prop) => proxy.$off(prop, queuedCallFn))
})
// Optional: If the watched function itself is reactive, remove this callback
if (isReactiveFunction(fn)) fn.$off(callFn)
}
// If the function is reactive, setup to re-run on reactive function changes
if (isReactiveFunction(fn)) fn.$on(callFn)
// Return the result of the initial function call and the cleanup function
return [result, unwatch];
}
Basically it would then return both the initial call result and a reference to the clean up function.
Example usage:
let unwatch;
onMount(() => {
// Setup the watch
const [watchResult, unwatch] = w(someReactiveFunction);
// Do something with watchResult if needed
});
onUnmount(() => {
// Clean up when the component unmounts
unwatch();
});
from arrow-js.
Related Issues (20)
- fails to render with multiple expressions in an attribute HOT 6
- TypeScript type for nested, optional reactive objects is broken HOT 1
- FYI: textarea behavior is very funky if you try to put HTML inside it rather than using the 'value' attribute HOT 2
- [Question] Are there ways to integrate with hyperscript interfaces? HOT 4
- Script throwing "Illegal Invocation" when adding an object to a reactive array HOT 2
- How does watch function work? HOT 2
- Cross-Site Scripting Vectors (XSS) HOT 5
- Dark mode flashbang 🫣 HOT 1
- Rewrite a reactive property which has $on event throw error
- [bug] Docs navigation indicator is bugged scrolling past "Getting Started" HOT 1
- Element property syntax not working HOT 1
- Map, Set, WeakMap, WeakSet can't be wrapped successfully HOT 4
- Nested template being called unexpectedly HOT 2
- Array of text boxes without a good key? HOT 2
- Poor performance? HOT 1
- What are the rules for `reactive`? Can I use es2015 classes in my "state" HOT 4
- Binding reactively to array length HOT 2
- Component that changes a sub-property of its own state object by async method re-renders the whole component in an infinite loop HOT 6
- Can it support the CommonJS
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from arrow-js.