Optimize computed by giving access to previous value
What problem does this feature solve?
If computed's getter returns an object, every time it's recalculated it will return a new object. It could be optimized if we would be able to get previously calculated value and in the case when nothing changes, we could just return the previous value without triggering watchers and other effects.
What does the proposed API look like?
const count = ref(23);
const result = computed((previous) => {
const digit = count.value % 10;
if (previous.digit == digit) return previous
return {
digit: digit.value,
label: $t(`digits.${digit}`)
}
});
You can build that yourself in like 3 lines of code.
const computedWithPrev = (cb) => {
let previous
return computed(() => previous = cb(previous))
}
Usage
const count = ref(23);
const result = computedWithPrev((previous) => {
const digit = count.value % 10;
if (previous.digit == digit) return previous
return {
digit: digit.value,
label: $t(`digits.${digit}`)
}
});
Also note that effects like component re-renders would still be triggered, the only thing you would be able to skip is watch callbacks.
If computed's getter returns an object, every time it's recalculated it will return a new object. It could be optimized if we would be able to get previously calculated value and in the case when nothing changes, we could just return the previous value without triggering watchers and other effects.
A problem with Javascript in general is that you cannot reliably or usefully check for equality (as in, {} !== {}
). But you can build a makeshift solution, using a watchEffect
to modify a ref
whenever it's relevant, per your equality criteria.
In any case, value equality of two objects is not an easy topic. What really determines whether two objects are equal? I suggest you take a look at Immutable.js, which could provide you with some useful tools to deal with this problem.
Given how easy it is to create your own composable and how much of an edge case this is, I don't thin it should be added to vue core. It could maybe be in vueuse if there is enough interest in it though