1# \@Track Decorator: Class Object Property-level Update
2
3
4\@Track is a decorator used to decorate properties of class objects. When a property decorated by \@Track changes, only the UI associated with the property is updated.
5
6
7> **NOTE**
8>
9> Since API version 11, this decorator is supported in ArkTS widgets.
10
11
12## Overview
13
14\@Track enables property-level UI updates. When a property of a class object is decorated by \@Track, changes to the property will trigger only updates to the UI associated with the property. Properties not decorated by \@Track cannot be used in the UI.
15
16
17## Decorator Description
18
19| \@Track Decorator | Description                 |
20| ------------------ | -------------------- |
21| Decorator parameters  | None.|
22| Allowed variable types| Non-static properties of class objects.|
23
24## Observed Changes and Behavior
25
26When 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.
27
28> **NOTE**
29>
30> When no property in the class object is decorated with \@Track, the behavior remains unchanged. \@Track is unable to observe changes of nested objects.
31
32Using the @Track decorator can avoid redundant re-renders.
33
34```ts
35class LogTrack {
36  @Track str1: string;
37  @Track str2: string;
38
39  constructor(str1: string) {
40    this.str1 = str1;
41    this.str2 = 'World';
42  }
43}
44
45class LogNotTrack {
46  str1: string;
47  str2: string;
48
49  constructor(str1: string) {
50    this.str1 = str1;
51    this.str2 = 'World';
52  }
53}
54
55@Entry
56@Component
57struct AddLog {
58  @State logTrack: LogTrack = new LogTrack('Hello');
59  @State logNotTrack: LogNotTrack = new LogNotTrack('Hello');
60
61  isRender(index: number) {
62    console.log(`Text ${index} is rendered`);
63    return 50;
64  }
65
66  build() {
67    Row() {
68      Column() {
69        Text(this.logTrack.str1) // UINode1
70          .fontSize(this.isRender(1))
71          .fontWeight(FontWeight.Bold)
72        Text(this.logTrack.str2) // UINode2
73          .fontSize(this.isRender(2))
74          .fontWeight(FontWeight.Bold)
75        Button('change logTrack.str1')
76          .onClick(() => {
77            this.logTrack.str1 = 'Bye';
78          })
79        Text(this.logNotTrack.str1) // UINode3
80          .fontSize(this.isRender(3))
81          .fontWeight(FontWeight.Bold)
82        Text(this.logNotTrack.str2) // UINode4
83          .fontSize(this.isRender(4))
84          .fontWeight(FontWeight.Bold)
85        Button('change logNotTrack.str1')
86          .onClick(() => {
87            this.logNotTrack.str1 = 'Goodbye';
88          })
89      }
90      .width('100%')
91    }
92    .height('100%')
93  }
94}
95```
96
97In the preceding example:
98
991. All attributes in the **LogTrack** class are decorated by @Track. After the **change logTrack.str1** button is clicked, **UINode1** is re-rendered, but **UINode2** is not, as indicated by that only one log record is generated.
100```ts
101Text 1 is rendered
102```
103
1042. None of the attributes in the **logNotTrack** class is decorated by @Track. After the **change logTrack.str1** button is clicked, both **UINode3** and **UINode4** are re-rendered, as indicated by that two log records are generated. Redundant re-renders occur.
105```ts
106Text 3 is rendered
107Text 4 is rendered
108```
109
110## Constraints
111
112- Properties that are not decorated by \@Track cannot be used in the UI, which means that such properties cannot be bound to components or be used to initialize child components. Incorrect use will cause JavaScript crashes. Yet, these properties can be used in non-UI cases, such as event callback functions and lifecycle functions.
113
114- Whenever possible, avoid any combination of class objects that contain \@Track and those that do not in, for example, union types and class inheritance.
115
116
117## Usage Scenarios
118
119### \@Track and Custom Component Updates
120
121This 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.
122
123
124```ts
125class Log {
126  @Track logInfo: string;
127  owner: string;
128  id: number;
129  time: Date;
130  location: string;
131  reason: string;
132
133  constructor(logInfo: string) {
134    this.logInfo = logInfo;
135    this.owner = 'OH';
136    this.id = 0;
137    this.time = new Date();
138    this.location = 'CN';
139    this.reason = 'NULL';
140  }
141}
142
143@Entry
144@Component
145struct AddLog {
146  @State log: Log = new Log('origin info.');
147
148  build() {
149    Row() {
150      Column() {
151        Text(this.log.logInfo)
152          .fontSize(50)
153          .fontWeight(FontWeight.Bold)
154          .onClick(() => {
155            // The properties without @Track can be used in the event handler.
156            console.log('owner: ' + this.log.owner +
157              ' id: ' + this.log.id +
158              ' time: ' + this.log.time +
159              ' location: ' + this.log.location +
160              ' reason: ' + this.log.reason);
161            this.log.time = new Date();
162            this.log.id++;
163
164            this.log.logInfo += ' info.';
165          })
166      }
167      .width('100%')
168    }
169    .height('100%')
170  }
171}
172```
173
174Processing steps:
175
1761. The click event **Text.onClick** of the **AddLog** custom component increases the value of **info**.
177
1782. 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.
179