58 lines
1.7 KiB
Markdown
58 lines
1.7 KiB
Markdown
---
|
|
title: Avoid Unnecessary Tracking
|
|
impact: HIGH
|
|
impactDescription: 20-40% fewer invalidations
|
|
tags: components, tracked, performance, reactivity
|
|
---
|
|
|
|
## Avoid Unnecessary Tracking
|
|
|
|
Only mark properties as `@tracked` if they need to trigger re-renders when changed. Overusing `@tracked` causes unnecessary invalidations and re-renders.
|
|
|
|
**Incorrect (everything tracked):**
|
|
|
|
```javascript
|
|
import Component from '@glimmer/component';
|
|
import { tracked } from '@glimmer/tracking';
|
|
import { action } from '@ember/object';
|
|
|
|
class Form extends Component {
|
|
@tracked firstName = ''; // Used in template ✓
|
|
@tracked lastName = ''; // Used in template ✓
|
|
@tracked _formId = Date.now(); // Internal, never rendered ✗
|
|
@tracked _validationCache = new Map(); // Internal state ✗
|
|
|
|
@action
|
|
validate() {
|
|
this._validationCache.set('firstName', this.firstName.length > 0);
|
|
// Unnecessary re-render triggered
|
|
}
|
|
}
|
|
```
|
|
|
|
**Correct (selective tracking):**
|
|
|
|
```javascript
|
|
import Component from '@glimmer/component';
|
|
import { tracked } from '@glimmer/tracking';
|
|
import { action } from '@ember/object';
|
|
|
|
class Form extends Component {
|
|
@tracked firstName = ''; // Rendered in template
|
|
@tracked lastName = ''; // Rendered in template
|
|
@tracked isValid = false; // Rendered status
|
|
|
|
_formId = Date.now(); // Not tracked - internal only
|
|
_validationCache = new Map(); // Not tracked - internal state
|
|
|
|
@action
|
|
validate() {
|
|
this._validationCache.set('firstName', this.firstName.length > 0);
|
|
this.isValid = this._validationCache.get('firstName');
|
|
// Only re-renders when isValid changes
|
|
}
|
|
}
|
|
```
|
|
|
|
Only track properties that directly affect the template or other tracked getters to minimize unnecessary re-renders.
|