@tracked Makes a Field Reactive
Tracked Properties
The tracked decorator is Ember's reactivity primitive — fields decorated with it trigger re-renders whenever they are set.
What you'll learn
- Decorate fields with the tracked decorator
- Set tracked values from action handlers
- Use derived getters that read tracked values
Ember Octane’s reactivity is built on @tracked. Any field you decorate with
it becomes reactive — writes invalidate templates and downstream getters that
read it.
Basic Use
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default class Counter extends Component {
@tracked count = 0;
get double() {
return this.count * 2;
}
@action
inc() {
this.count++;
}
} The template re-renders automatically when count is mutated. Notice double
is just a getter — Glimmer sees it reads this.count and tracks it.
Mutate By Replacement
Tracked deep mutations are not picked up — you have to replace the reference:
@tracked items = [];
@action
add(item) {
// BAD: this.items.push(item) — won't re-render
this.items = [...this.items, item];
} For convenience, tracked-built-ins offers TrackedArray and TrackedObject
which track mutations under the hood.
Tracked On Any Class
@tracked works on services, utility classes, anything — not just components.
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
export default class CartService extends Service {
@tracked items = [];
get count() {
return this.items.length;
}
} Any template that reads cart.count will update when items is reassigned.