Subscribe on changes!

Optimize computed by giving access to previous value

avatar
Jan 26th 2022

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}`)
  }
});
avatar
Jan 26th 2022

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.

avatar
Jan 26th 2022

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.

avatar
Jan 27th 2022

What is the definition for the feature who is good to discuss?

avatar
Jan 27th 2022

I'm not sure I understand the question.

avatar
Jan 28th 2022

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

avatar
Jan 28th 2022

Okay, I thought doing it in core would be better, but you are right, it's easy to implement manually, thanks @LinusBorg