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