• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# \@State: 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. For details about the scenarios of nested 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>Avoid using this decorator to decorate the Date type, as doing so may lead to unexpected behavior of the application.<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   | Mandatory.                                   |
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.<br>An \@State decorated variable can be initialized from a regular variable 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![en-us_image_0000001502091796](figures/en-us_image_0000001502091796.png)
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
157### Framework Behavior
158
159- When a state variable is changed, the framework searches for components that depend on this state variable.
160
161- The framework executes an update method of the dependent components, which triggers re-rendering of the components.
162
163- Components or UI descriptions irrelevant to the state variable are not re-rendered, thereby implementing on-demand page updates.
164
165
166## Application Scenarios
167
168
169### Decorating Variables of Simple Types
170
171In this example, \@State is used to decorate the **count** variable of the simple type and turns it into a state variable. The change of **count** causes the update of the **\<Button>** component.
172
173- When the state variable **count** changes, the framework searches for components that depend on this state variable, which include only the **\<Button>** component in this example.
174
175- The framework executes the update method of the **\<Button>** component to implement on-demand update.
176
177
178```ts
179@Entry
180@Component
181struct MyComponent {
182  @State count: number = 0;
183
184  build() {
185    Button(`click times: ${this.count}`)
186      .onClick(() => {
187        this.count += 1;
188      })
189  }
190}
191```
192
193
194### Decorating Variables of the Class Object Type
195
196- 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.
197
198- The **EntryComponent** has multiple **MyComponent** instances. The internal state change of the first **MyComponent** instance does not affect the second **MyComponent** instance.
199
200
201
202```ts
203class Model {
204  public value: string;
205
206  constructor(value: string) {
207    this.value = value;
208  }
209}
210
211@Entry
212@Component
213struct EntryComponent {
214  build() {
215    Column() {
216      // 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.
217      MyComponent({ count: 1, increaseBy: 2 })
218      MyComponent({ title: new Model('Hello, World 2'), count: 7 })
219    }
220  }
221}
222
223@Component
224struct MyComponent {
225  @State title: Model = new Model('Hello World');
226  @State count: number = 0;
227  private increaseBy: number = 1;
228
229  build() {
230    Column() {
231      Text(`${this.title.value}`)
232      Button(`Click to change title`).onClick(() => {
233        // The update of the @State decorated variable triggers the update of the <Text> component.
234        this.title.value = this.title.value === 'Hello ArkUI' ? 'Hello World' : 'HelloArkUI';
235      })
236
237      Button(`Click to increase count=${this.count}`).onClick(() => {
238        // The update of the @State decorated variable triggers the update of the <Button> component.
239        this.count += this.increaseBy;
240      })
241    }
242  }
243}
244```
245
246
247From this example, we learn the initialization process of an \@State decorated variable on initial render.
248
249
2501. Apply the locally defined default value.
251
252   ```ts
253   @State title: Model = new Model('Hello World');
254   @State count: number = 0;
255   ```
256
2572. Apply the named parameter value, if one is provided.
258
259   ```ts
260   MyComponent({ count: 1, increaseBy: 2 })
261   ```
262