1# \@State Decorator: State Owned by Component 2 3 4An \@State decorated variable, also called a state variable, is a variable that holds the state property and is used to render the owning custom component. When it changes, the UI is re-rendered accordingly. 5 6 7Among the decorators related to state variables, \@State is the most basic decorator, as it is the one that empowers variables to have the state property. It is also the data source of most state variables. 8 9 10> **NOTE** 11> 12> Since API version 9, this decorator is supported in ArkTS widgets. 13 14 15## Overview 16 17An @State decorated variable, like all other decorated variables in the declarative paradigm, are private and only accessible from within the component. Its type and its local initialization must be specified. Initialization from the parent component using the named parameter mechanism is accepted. 18 19\@State decorated variables have the following features: 20 21- A one-way and two-way data synchronization relationship can be set up from an \@State decorated variable to an \@Prop, \@Link, or \@ObjectLink decorated variable in a child component. 22 23- The lifecycle of the \@State decorated variable is the same as that of its owning custom component. 24 25 26## Rules of Use 27 28| \@State Decorator | Description | 29| ------------------ | ------------------------------------------------------------ | 30| Decorator parameters | None. | 31| Synchronization type | Does not synchronize with any type of variable in the parent component. | 32| Allowed variable types| Object, class, string, number, Boolean, enum, and array of these types.<br>Date type.<br>For details about the scenarios of supported types, see [Observed Changes](#observed-changes).<br>The type must be specified.<br>**any** is not supported. A combination of simple and complex types is not supported. The **undefined** and **null** values are not allowed.<br>**NOTE**<br>The Length, ResourceStr, and ResourceColor types are a combination of simple and complex types and therefore not supported.| 33| Initial value for the decorated variable| Local initialization is required. | 34 35 36## Variable Transfer/Access Rules 37 38| Transfer/Access | Description | 39| ------------------ | ------------------------------------------------------------ | 40| Initialization from the parent component | Optional. Initialization from the parent component or local initialization can be used. The initial value specified in the parent component will overwrite the one defined locally.<br>An @State decorated variable can be initialized from a regular variable (whose change does not trigger UI refresh) or an @State, @Link, @Prop, @Provide, @Consume, @ObjectLink, @StorageLink, @StorageProp, @LocalStorageLink, or @LocalStorageProp decorated variable in its parent component.| 41| Subnode initialization | Supported. An \@State decorated variable can be used to initialize a regular variable or \@State, \@Link, \@Prop, or \@Provide decorated variable in the child component.| 42| Access| Private, accessible only within the component. | 43 44 **Figure 1** Initialization rule 45 46 47 48 49## Observed Changes and Behavior 50 51Not all changes to state variables cause UI updates. Only changes that can be observed by the framework do. This section describes what changes can be observed and how the framework triggers UI updates after the changes are observed, that is, how the framework behaves. 52 53 54### Observed Changes 55 56- When the decorated variable is of the Boolean, string, or number type, its value change can be observed. 57 58 ```ts 59 // for simple type 60 @State count: number = 0; 61 // value changing can be observed 62 this.count = 1; 63 ``` 64 65- When the decorated variable is of the class or Object type, its value change and value changes of all its attributes, that is, the attributes that **Object.keys(observedObject)** returns. Below is an example. 66 Declare the **ClassA** and **Model** classes. 67 68 ```ts 69 class ClassA { 70 public value: string; 71 72 constructor(value: string) { 73 this.value = value; 74 } 75 } 76 77 class Model { 78 public value: string; 79 public name: ClassA; 80 constructor(value: string, a: ClassA) { 81 this.value = value; 82 this.name = a; 83 } 84 } 85 ``` 86 87 Use \@State to decorate a variable of the Model class object type. 88 89 ```ts 90 // Class type 91 @State title: Model = new Model('Hello', new ClassA('World')); 92 ``` 93 94 Assign a value to the \@State decorated variable. 95 96 ```ts 97 // Assign a value to the class object. 98 this.title = new Model('Hi', new ClassA('ArkUI')); 99 ``` 100 101 Assign a value to an attribute of the \@State decorated variable. 102 103 ```ts 104 // Assign a value to an attribute of the class object. 105 this.title.value = 'Hi' 106 ``` 107 108 The value assignment of the nested attribute cannot be observed. 109 110 ```ts 111 // The value assignment of the nested attribute cannot be observed. 112 this.title.name.value = 'ArkUI' 113 ``` 114- When the decorated variable is of the array type, the addition, deletion, and updates of array items can be observed. Below is an example. 115 Declare the **ClassA** and **Model** classes. 116 117 ```ts 118 class Model { 119 public value: number; 120 constructor(value: number) { 121 this.value = value; 122 } 123 } 124 ``` 125 126 Use \@State to decorate a variable of the Model class array type. 127 128 ```ts 129 @State title: Model[] = [new Model(11), new Model(1)] 130 ``` 131 132 The value assignment of the array itself can be observed. 133 134 ```ts 135 this.title = [new Model(2)] 136 ``` 137 138 The value assignment of array items can be observed. 139 140 ```ts 141 this.title[0] = new Model(2) 142 ``` 143 144 The deletion of array items can be observed. 145 146 ```ts 147 this.title.pop() 148 ``` 149 150 The addition of array items can be observed. 151 152 ```ts 153 this.title.push(new Model(12)) 154 ``` 155 156- When the decorated variable is of the Date type, the overall value assignment of the Date object can be observed, and the following APIs can be called to update Date attributes: **setFullYear**, **setMonth**, **setDate**, **setHours**, **setMinutes**, **setSeconds**, **setMilliseconds**, **setTime**, **setUTCFullYear**, **setUTCMonth**, **setUTCDate**, **setUTCHours**, **setUTCMinutes**, **setUTCSeconds**, and **setUTCMilliseconds**. 157 158 ```ts 159 @Entry 160 @Component 161 struct DatePickerExample { 162 @State selectedDate: Date = new Date('2021-08-08') 163 164 build() { 165 Column() { 166 Button('set selectedDate to 2023-07-08') 167 .margin(10) 168 .onClick(() => { 169 this.selectedDate = new Date('2023-07-08') 170 }) 171 Button('increase the year by 1') 172 .margin(10) 173 .onClick(() => { 174 this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1) 175 }) 176 Button('increase the month by 1') 177 .margin(10) 178 .onClick(() => { 179 this.selectedDate.setMonth(this.selectedDate.getMonth() + 1) 180 }) 181 Button('increase the day by 1') 182 .margin(10) 183 .onClick(() => { 184 this.selectedDate.setDate(this.selectedDate.getDate() + 1) 185 }) 186 DatePicker({ 187 start: new Date('1970-1-1'), 188 end: new Date('2100-1-1'), 189 selected: this.selectedDate 190 }) 191 }.width('100%') 192 } 193 } 194 ``` 195 196### Framework Behavior 197 198- When a state variable is changed, the framework searches for components that depend on this state variable. 199 200- The framework executes an update method of the dependent components, which triggers re-rendering of the components. 201 202- Components or UI descriptions irrelevant to the state variable are not re-rendered, thereby implementing on-demand page updates. 203 204 205## Application Scenarios 206 207 208### Decorating Variables of Simple Types 209 210In this example, \@State is used to decorate the **count** variable of the simple type, turning it into a state variable. The change of **count** causes the update of the **\<Button>** component. 211 212- When **count** changes, the framework searches for components bound to it, which include only the **\<Button>** component in this example. 213 214- The framework executes the update method of the **\<Button>** component to implement on-demand update. 215 216 217```ts 218@Entry 219@Component 220struct MyComponent { 221 @State count: number = 0; 222 223 build() { 224 Button(`click times: ${this.count}`) 225 .onClick(() => { 226 this.count += 1; 227 }) 228 } 229} 230``` 231 232 233### Decorating Variables of the Class Object Type 234 235- In this example, \@State is used to decorate the variables **count** and **title** in the custom component **MyComponent**. The type of **title** is **Model**, a custom class. If the value of **count** or **title** changes, the framework searches for all **MyComponent** instances that depend on these variables and triggers re-rendering of them. 236 237- The **EntryComponent** has multiple **MyComponent** instances. The internal state change of the first **MyComponent** instance does not affect the second **MyComponent** instance. 238 239 240 241```ts 242class Model { 243 public value: string; 244 245 constructor(value: string) { 246 this.value = value; 247 } 248} 249 250@Entry 251@Component 252struct EntryComponent { 253 build() { 254 Column() { 255 // The parameters specified here will overwrite the default values defined locally during initial render. Not all parameters need to be initialized from the parent component. 256 MyComponent({ count: 1, increaseBy: 2 }) 257 MyComponent({ title: new Model('Hello, World 2'), count: 7 }) 258 } 259 } 260} 261 262@Component 263struct MyComponent { 264 @State title: Model = new Model('Hello World'); 265 @State count: number = 0; 266 private increaseBy: number = 1; 267 268 build() { 269 Column() { 270 Text(`${this.title.value}`) 271 Button(`Click to change title`).onClick(() => { 272 // The update of the @State decorated variable triggers the update of the <Text> component. 273 this.title.value = this.title.value === 'Hello ArkUI' ? 'Hello World' : 'Hello ArkUI'; 274 }) 275 276 Button(`Click to increase count=${this.count}`).onClick(() => { 277 // The update of the @State decorated variable triggers the update of the <Button> component. 278 this.count += this.increaseBy; 279 }) 280 } 281 } 282} 283``` 284 285 286From this example, we learn the initialization process of an \@State decorated variable on initial render. 287 288 2891. Apply the locally defined default value. 290 291 ```ts 292 @State title: Model = new Model('Hello World'); 293 @State count: number = 0; 294 ``` 295 2962. Apply the named parameter value, if one is provided. 297 298 ```ts 299 class C1 { 300 public count:number; 301 public increaseBy:number; 302 constructor(count: number, increaseBy:number) { 303 this.count = count; 304 this.increaseBy = increaseBy; 305 } 306 } 307 let obj = new C1(1, 2) 308 MyComponent(obj) 309 ``` 310