1# \@Track Decorator: Class Object Property-level Update
2
3
4\@Track is a decorator used to decorate properties of class objects. Any changes to the properties decorated by \@Track will trigger only updates to the UI associated with those properties.
5
6
7Before reading this topic, you are advised to read [\@State](./arkts-state.md) to have a basic understanding of the observation capabilities of state management.
8
9> **NOTE**
10>
11> This decorator is supported in ArkTS widgets since API version 11.
12
13
14## Overview
15
16\@Track enables property-level update for the class object. When a class object is a state variable, the change of the \@Track decorated property triggers only the update of the property associated UI. If the class uses the \@Track decorator, the properties that are not decorated by \@Track cannot be used in the UI. Otherwise, a runtime error is reported.
17
18
19## Decorator Description
20
21| \@Track Decorator | Description                 |
22| ------------------ | -------------------- |
23| Decorator parameters  | None.|
24| Allowed variable types| Non-static properties of class objects.|
25
26## Observed Changes and Behavior
27
28When a class object is a state variable, any changes to its properties decorated by \@Track will trigger only updates to the UI associated with those properties.
29
30> **NOTE**
31>
32> When no property in the class object is decorated with \@Track, the behavior remains unchanged. \@Track is unable to observe changes of nested objects.
33
34Using the @Track decorator can avoid redundant updates.
35
36```ts
37class LogTrack {
38  @Track str1: string;
39  @Track str2: string;
40
41  constructor(str1: string) {
42    this.str1 = str1;
43    this.str2 = 'World';
44  }
45}
46
47class LogNotTrack {
48  str1: string;
49  str2: string;
50
51  constructor(str1: string) {
52    this.str1 = str1;
53    this.str2 = 'World';
54  }
55}
56
57@Entry
58@Component
59struct AddLog {
60  @State logTrack: LogTrack = new LogTrack('Hello');
61  @State logNotTrack: LogNotTrack = new LogNotTrack('Hello');
62
63  isRender(index: number) {
64    console.log(`Text ${index} is rendered`);
65    return 50;
66  }
67
68  build() {
69    Row() {
70      Column() {
71        Text(this.logTrack.str1) // Text1
72          .fontSize(this.isRender(1))
73          .fontWeight(FontWeight.Bold)
74        Text(this.logTrack.str2) // Text2
75          .fontSize(this.isRender(2))
76          .fontWeight(FontWeight.Bold)
77        Button('change logTrack.str1')
78          .onClick(() => {
79            this.logTrack.str1 = 'Bye';
80          })
81        Text(this.logNotTrack.str1) // Text3
82          .fontSize(this.isRender(3))
83          .fontWeight(FontWeight.Bold)
84        Text(this.logNotTrack.str2) // Text4
85          .fontSize(this.isRender(4))
86          .fontWeight(FontWeight.Bold)
87        Button('change logNotTrack.str1')
88          .onClick(() => {
89            this.logNotTrack.str1 = 'Goodbye';
90          })
91      }
92      .width('100%')
93    }
94    .height('100%')
95  }
96}
97```
98
99In the preceding example:
100
1011. All properties in the **LogTrack** class are decorated by \@Track. After the **change logTrack.str1** button is clicked, **Text1** is updated, but **Text2** is not, as indicated by that only one log record is generated.
102    ```ts
103    Text 1 is rendered
104    ```
105
1062. None of the properties in the **logNotTrack** class is decorated by \@Track. After the **change logTrack.str1** button is clicked, both **Text3** and **Text4** are updated, as indicated by that two log records are generated. Redundant updates occur.
107    ```ts
108    Text 3 is rendered
109    Text 4 is rendered
110    ```
111
112## Constraints
113
114- If the \@Track decorator is used in a class, the non-\@Track decorated properties in the class cannot be used in the UI. For example, these properties cannot be bound to components nor be used to initialize child components; otherwise, an error is reported during runtime. For details, see [Improperly Using Non-\@Track Decorated Properties Causes Errors](#improperly-using-non-track-decorated-properties-causes-errors). Non-\@Track decorated properties can be used in non-UI functions, such as event callback functions and lifecycle functions.
115
116- Whenever possible, avoid any combination of class objects that contain \@Track and those that do not in, for example, union types and class inheritance.
117
118
119## Use Scenarios
120
121### \@Track and Custom Component Updates
122
123This example is used to clarify the processing steps of custom component updates and \@Track. The **log** object is a state variable decorated by \@State. Its **logInfo** property is decorated by \@Track, but other properties are not, and the values of these other properties are not updated through the UI.
124
125
126```ts
127class Log {
128  @Track logInfo: string;
129  owner: string;
130  id: number;
131  time: Date;
132  location: string;
133  reason: string;
134
135  constructor(logInfo: string) {
136    this.logInfo = logInfo;
137    this.owner = 'OH';
138    this.id = 0;
139    this.time = new Date();
140    this.location = 'CN';
141    this.reason = 'NULL';
142  }
143}
144
145@Entry
146@Component
147struct AddLog {
148  @State log: Log = new Log('origin info.');
149
150  build() {
151    Row() {
152      Column() {
153        Text(this.log.logInfo)
154          .fontSize(50)
155          .fontWeight(FontWeight.Bold)
156          .onClick(() => {
157            // Properties that are not decorated by @Track can be used in click events.
158            console.log('owner: ' + this.log.owner +
159              ' id: ' + this.log.id +
160              ' time: ' + this.log.time +
161              ' location: ' + this.log.location +
162              ' reason: ' + this.log.reason);
163            this.log.time = new Date();
164            this.log.id++;
165
166            this.log.logInfo += ' info.';
167          })
168      }
169      .width('100%')
170    }
171    .height('100%')
172  }
173}
174```
175
176Processing steps:
177
1781. The click event **Text.onClick** of the **AddLog** custom component increases the value of **info**.
179
1802. In response to the change of the \@State decorated variable **log**, the \@Track decorated property **logInfo** is updated, and the **Text** component is re-rendered.
181
182## FAQs
183
184### Improperly Using Non-\@Track Decorated Properties Causes Errors
185
186If a property that is not decorated by \@Track is used in the UI, an error is reported during runtime.
187
188```ts
189class Person {
190  // id is decorated by @Track.
191  @Track id: number;
192  // age is not decorated by @Track.
193  age: number;
194
195  constructor(id: number, age: number) {
196    this.id = id;
197    this.age = age;
198  }
199}
200
201@Entry
202@Component
203struct Parent {
204  @State parent: Person = new Person(2, 30);
205
206  build() {
207    // Property that is not decorated by @Track cannot be used in the UI. Otherwise, an error is reported during runtime.
208    Text(`Parent id is: ${this.parent.id} and Parent age is: ${this.parent.age}`)
209  }
210}
211```
212