• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 an understanding of the basic 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
27
28## Observed Changes and Behavior
29
30When 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.
31
32> **NOTE**
33>
34> When no property in the class object is decorated with \@Track, the behavior remains unchanged. \@Track is unable to observe changes of nested objects.
35
36Using the @Track decorator can avoid redundant updates.
37
38```ts
39class LogTrack {
40  @Track str1: string;
41  @Track str2: string;
42
43  constructor(str1: string) {
44    this.str1 = str1;
45    this.str2 = 'World';
46  }
47}
48
49class LogNotTrack {
50  str1: string;
51  str2: string;
52
53  constructor(str1: string) {
54    this.str1 = str1;
55    this.str2 = 'World';
56  }
57}
58
59@Entry
60@Component
61struct AddLog {
62  @State logTrack: LogTrack = new LogTrack('Hello');
63  @State logNotTrack: LogNotTrack = new LogNotTrack('Hello');
64
65  isRender(index: number) {
66    console.log(`Text ${index} is rendered`);
67    return 50;
68  }
69
70  build() {
71    Row() {
72      Column() {
73        Text(this.logTrack.str1) // Text1
74          .fontSize(this.isRender(1))
75          .fontWeight(FontWeight.Bold)
76        Text(this.logTrack.str2) // Text2
77          .fontSize(this.isRender(2))
78          .fontWeight(FontWeight.Bold)
79        Button('change logTrack.str1')
80          .onClick(() => {
81            this.logTrack.str1 = 'Bye';
82          })
83        Text(this.logNotTrack.str1) // Text3
84          .fontSize(this.isRender(3))
85          .fontWeight(FontWeight.Bold)
86        Text(this.logNotTrack.str2) // Text4
87          .fontSize(this.isRender(4))
88          .fontWeight(FontWeight.Bold)
89        Button('change logNotTrack.str1')
90          .onClick(() => {
91            this.logNotTrack.str1 = 'Goodbye';
92          })
93      }
94      .width('100%')
95    }
96    .height('100%')
97  }
98}
99```
100
101In the preceding example:
102
1031. 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.
104    ```ts
105    Text 1 is rendered
106    ```
107
1082. 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.
109    ```ts
110    Text 3 is rendered
111    Text 4 is rendered
112    ```
113
114## Constraints
115
116- If the \@Track decorator is used in a class, the non-\@Track decorated properties in the class cannot be used in the \@Component decorated 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.
117
118- Since API version 18 and later, \@Track is used in the \@ComponentV2 decorated UI. In this case, an error is not reported during runtime, but the refresh is not responded. For details, see [Common Scenarios](./arkts-v1-v2-mixusage.md#observed-decorated-class).
119
120- Whenever possible, avoid any combination of class objects that contain \@Track and those that do not in, for example, union types and class inheritance.
121
122
123## Use Scenarios
124
125### \@Track and Custom Component Updates
126
127This 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.
128
129
130```ts
131class Log {
132  @Track logInfo: string;
133  owner: string;
134  id: number;
135  time: Date;
136  location: string;
137  reason: string;
138
139  constructor(logInfo: string) {
140    this.logInfo = logInfo;
141    this.owner = 'OH';
142    this.id = 0;
143    this.time = new Date();
144    this.location = 'CN';
145    this.reason = 'NULL';
146  }
147}
148
149@Entry
150@Component
151struct AddLog {
152  @State log: Log = new Log('origin info.');
153
154  build() {
155    Row() {
156      Column() {
157        Text(this.log.logInfo)
158          .fontSize(50)
159          .fontWeight(FontWeight.Bold)
160          .onClick(() => {
161            // Properties that are not decorated by @Track can be used in click events.
162            console.log('owner: ' + this.log.owner +
163              ' id: ' + this.log.id +
164              ' time: ' + this.log.time +
165              ' location: ' + this.log.location +
166              ' reason: ' + this.log.reason);
167            this.log.time = new Date();
168            this.log.id++;
169
170            this.log.logInfo += ' info.';
171          })
172      }
173      .width('100%')
174    }
175    .height('100%')
176  }
177}
178```
179
180Processing steps:
181
1821. The click event **Text.onClick** of the **AddLog** custom component increases the value of **info**.
183
1842. 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.
185
186## FAQs
187
188### Improperly Using Non-\@Track Decorated Properties Causes Errors
189
190If a non-\@Track decorated property is used in the UI, an error is reported during runtime.
191
192```ts
193class Person {
194  // id is decorated by @Track.
195  @Track id: number;
196  // age is not decorated by @Track.
197  age: number;
198
199  constructor(id: number, age: number) {
200    this.id = id;
201    this.age = age;
202  }
203}
204
205@Entry
206@Component
207struct Parent {
208  @State parent: Person = new Person(2, 30);
209
210  build() {
211    // Property that is not decorated by @Track cannot be used in the UI. Otherwise, an error is reported during runtime.
212    Text(`Parent id is: ${this.parent.id} and Parent age is: ${this.parent.age}`)
213  }
214}
215```
216