-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Value-like equality in computed #802
Comments
@jamiewinder did you try |
Ability to provide own comparator has been already proposed, but it's probably not needed that often... Some other workarounds:
const currentDate = computed(() => {
const nextDate = LocalDate.ofInstant(Instant.ofEpochMilli(now(10000)));
});
const currentDateAsString = computed(() => {
return currentDate.get().toString(); // or timestamp or anything comparable by value/reference/structure
});
autorun(() => {
document.write(currentDateAsString.get());
// it's a bit hacky but you can still access currentDate without subscribing via Mobx.untracked
});
const boxedLocalDate = Mobx.observable.box(LocalDate.ofInstant(Instant.ofEpochMilli(Date.now()));
reaction(() => MobxUtils.now(10000), epochMilli => {
const newDate = LocalDate.ofInstant(Instant.ofEpochMilli(epochMilli));
if (!boxedLocalDate.get().equals(newDate)) {
boxedLocalDate.set(newDate);
}
});
autorun(() => {
document.write(boxedLocalDate.get().toString());
});
// Don't forget to dispose reaction after you dispose autorun EDIT: @mweststrate even if |
@mweststrate - I don't think The name suggests it'd fit the bill in this case as I think all the comparable properties of a @urugator - Thanks for the suggestion. I've currently gone for this general solution: function computedWithComparator<T>(
func: () => T,
eq: (a: T, b: T) => boolean,
setter?: (value: T) => void
) {
let firstTime = true;
let lastEmitted: T;
return computed(() => {
const value = func();
if (firstTime || !eq(value, lastEmitted )) {
lastEmitted = value;
firstTime = false;
}
return lastEmitted;
}, setter);
} It's a bit of a clumsy name, but it seems to be doing the trick. Usage: const currentDate = computedWithComparator(
() => LocalDate.ofInstant(Instant.ofEpochMilli(now(10000))),
(a, b) => a.equals(b)
); |
You can pass options to computed function (would be nice to have anchors on headings) |
@jamiewinder, yes, should work as direct api as well, or pass |
Thanks both, I didn't know about the computed options argument! Just when I thought I knew it all..! I can submit this to mobx-utils too if you think it's useful, but might it be better as another option on the standard Thanks again |
@mweststrate Some more thoughts on this for critique!: // Extra 'equals' option on computed options (could be a better term). Takes the last emitted value and the new computed value, and returns `true` if they're considered equal, otherwise `false`. This won't be called the first time a computed is calculated.
computed(() => {
return ...;
}, { equals: (a, b) => a.isEqualTo(b) });
// This mimics the current behaviour
computed(() => {
return ...;
}, { equals: (a, b) => a === b);
// This is the same as { compareStructual: true }
computed(() => {
return ...;
}, { equals: (a, b) => deepEquals(a, b)); It might get messy on a decorator, but maybe: const localDateEqual = (a: LocalDate, b: LocalDate) => a.equals(b);
// ...
@computed({ equals: localDateEqual }) public get today() {
return ...;
} Or maybe, gulp: const computedLocalDate = createComputedDecorator<LocalDate>({ equals: (a, b) => a.equals(b) });
@computedLocalDate public get today() {
return ...;
}
@computedLocalDate public get yesterday() {
return ...;
} |
Sorry for the late response @jamiewinder! An additionals |
Version 3.2.1 added support for custom equality checks. Thanks @jamiewinder! |
I have the following code:
This basically produces an observable
LocalDate
value based on mobx-utils'now
utility which will be accurate enough for my use (never more than 10 seconds out). However, the computed itself will observably change every 10 seconds, despite the practical 'value' of the returned object very rarely changing.This for example will log every 10 seconds, not ~ once a day:
Is there a better way I could be doing this? It'd be nice to be able to instruct MobX how to determine equality of the return values (i.e.
(a, b) => a.equalTo(b)
) so it knows when the computed value should observably change.EDIT: This appears to achieve what I'm after, but is a little hacky:
The text was updated successfully, but these errors were encountered: