Vue, Angular, React Comparison Series: computed property
Tags: vue, angular, react, javascript
Published: 2020-04-24 06:40:43

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3klhsqpmkgu0cuq1v1ds.png)

Versions used are:
Vue 2.x , React 16.8.x, Angular 9.x

### What is a computed property
When rendering value of a property on template, it can be either a simple value like string, number, a single expression or a result of a more complex computation that can be expensive to perform. A computed property does caching when the input stays the same so that the performance can be much better in a heavy computation scenario.

In the example below, there are two values that we want to display:
- **name** property which is initialized to a value
- **fullname** property is the computed property that depends on **name** property. Every time **name** is updated, the updated **fullname** should be rendered.
- **getFullname()** method is a regular method that shows what would happen without caching
- **count** property triggered by Count button is used to trigger template rendering every time the **count** value is incremented, so that we can see what happens to **fullname** property when rendering happens outside of its dependency scope.
- **counter** property is an object with a primitive value property called **count**. This is to show the case where the dependent is an object
- Change Name button is used to modify **name** property once, to show that a computed property is recalculated when its dependents modified.

###Vue
In Vue, to display complex expression, we can use: **computed**, **methods**, **filters**
A method defined in **computed** is cached and only called again when the dependents are changed; a method defined in **methods** and **filters** are always called every time the render happens - every time **count** is incremented. Vue computed property is either doing a deep comparison or recreate **this.counter** to compare by reference for object type, as we can see that **this.counter.count** is just simply updated on the template without any issue.

```javascript
computed: {
    fullname() {
      console.log("render fullname");
      return `${this.name} framework`;
    }
  },
```
{% codesandbox vue-computed-pfe0n %}

###React
In React, we have: **useMemo** and regular **function**
useMemo only recomputes when its dependency: **name** is changed.
Since useState assign a **counter** object with the incremented count, the object change by reference can be performed and render the updated value of **this.counter.count**

```javascript
const fullname = useMemo(() => {
    console.log("render fullname");
    return `${name} library`;
  }, [name]);
```
{% codesandbox react-computed-7xsbq %}

###Angular
In Angular, we have: Pipe which is the equivalent of Vue's **filters** but has caching feature. Angular pipe is pure by default, so if the input is an object instead of primitive type like string, the comparison by reference is performed. 
Using impure pipe, we can detect object mutation. As we can see in the example, if the pure is set to false, then the counter pipe can detect the counter object change.
```javascript
@Pipe({ name: "getFullNamePipe" })
export class getFullNamePipe implements PipeTransform {
  transform(name: string): string {
    console.log(`Pipe as Angular's computed property`);
    return `${name} framework`;
  }
}
``` 
{% codesandbox angular-computed-bg13r %}