-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
avoid updates when value did not change (with custom equality function) #25
Comments
Hey, looks like we can work around this "in userspace", using the previous value we get in import { observable, Observable } from 'micro-observables';
export type Equality<T> = (a: T, b: T) => boolean;
/**
* Takes an observable and produces a new one, which updates
* only if equals returns false.
* Example usage:
* const obs2 = sameIf(isEqual)(obs1)
**/
export function sameIf<T>(equals: Equality<T>) {
return (original: Observable<T>): Observable<T> => {
const derived = observable(original.get());
original.subscribe((newVal: T, oldVal: T) => {
if (!equals(newVal, oldVal)) {
derived.set(newVal);
}
});
return derived;
};
}
// or, if you prefer it as a constructor
export function observableMemo<T>(value: T, equals: Equality<T>): Observable<T> {
return sameIf(equals)(observable(value));
} (sorry about the indents, github seems to mess them up no matter what i do) codesandbox with some react code to check it out: You'd still need to wrap everything with const selectIf = (equals) => (obs, selector) => sameIf(equals)(obs.select(selector)) Some alternative names: |
This is something I am doing right now, but I am afraid that this solution is prone to memory leaks. I assume that a regularly derived observable via Using the solution outlined by lubieowoce, by explicitly creating a subscription on the source observable and referencing the target observable, we bind the lifetime of the target observable to the source observable, and cannot simply "let it go". I noticed that there is an undocumented Plugin architecture in the library that supports stuff like |
Yes, you're right, deriving observables using I agree that equality function is definitely something that should be built-in directly in micro-observables. We actually already added support for it in the next major version of the library (that is not released yet). I've quickly tried to backport it into the 1.x version but unfortunately, this is not straightforward. The next version should hopefully be released in the next few weeks.
This API was an experiment to add support for persistence and dev tools to |
hey @simontreny any updates on this one? would be cool to see 2.x and also if you've considered react v18 concurrent mode + useSyncExternalStore ? |
I have a graph of observables, that originate from a rapidly changing one (a redux store that we want to migrate away from).
I want derived observables to only propagate updates if their value actually changed.
I want to use a custom equality function to determine if something changed (e.g. structual equality over reference equality).
I know that I can compare current and last value inside
subscribe
, but most of my observables are not directly subscribed, but are used as inputs to other observables, which are unnessecarily recomputed.I propose an additional, optional parameter
isEqual(next: T, current: T): boolean
, to.select()
and.compute()
, after the lambda function, where you can pass in an equality function that is evaluated on every update after the initialitation of the observable. If it returnstrue
, the observable is not updated with the computed value.The text was updated successfully, but these errors were encountered: