# State Management with Page-level Variables This topic covers how to manage the states with page-level variables with the **@State**, **@Prop**, **@Link**, **@Provide**, **@Consume**, **@ObjectLink**, **@Observed**, and **@Watch** decorators. For details about the constraints of the **@State**, **@Provide**, **@Link**, and **@Consume** decorated state variables, see [Restrictions on Data Type Declarations of State Variables](./arkts-restrictions-and-extensions.md). ## @State The **@State** decorated variable is the internal state data of the component. When the state data is modified, the **build** method of the component is called to refresh the UI. The **@State** data has the following features: - Support for multiple types: The following types are supported: strong types by value and by reference, including **class**, **number**, **boolean**, **string**, as well as arrays of these types, that is, **Array\**, **Array\**, **Array\**, and **Array\**. **object** and **any** are not supported. - Support for multiple instances: Multiple instances can coexist in a component. The internal state data of different instances is independent. - **Private**: An attribute marked with **@State** can only be accessed within the component. - Local initialization required: Initial values must be allocated to all **@State** decorated variables. Uninitialized variables may cause undefined framework exceptions. - Support for setting of initial attribute values based on the state variable name: When creating a component instance, you can explicitly specify the initial value of the **@State** decorated attribute based on the variable name. **Example** In the following example: - Two **@State** decorated variables, **count** and **title**, have been defined for **MyComponent**. If the value of **count** or **title** changes, the **build** method of **MyComponent** needs to be called to render the component again. - The **EntryComponent** has multiple **MyComponent** instances. The internal status change of the first **MyComponent** instance does not affect the second **MyComponent** instance. - When creating a **MyComponent** instance, initialize the variables in the component based on the variable name. For example: ```ts MyComponent({ title: { value: 'Hello World 2' }, count: 7 }) ``` ```ts // xxx.ets class Model { value: string constructor(value: string) { this.value = value } } @Entry @Component struct EntryComponent { build() { Column() { MyComponent ({ count: 1,increaseBy:2 }) // First MyComponent instance MyComponent({ title: { value:'Hello World 2' }, count: 7 }) // Second MyComponent instance } } } @Component struct MyComponent { @State title: Model = { value: 'Hello World' } @State count: number = 0 private toggle: string = 'Hello World' private increaseBy: number = 1 build() { Column() { Text(`${this.title.value}`).fontSize(30) Button('Click to change title') .margin(20) .onClick(() => { // Change the value of the internal status variable title. this.title.value = (this.toggle == this.title.value) ? 'Hello World' : 'Hello ArkUI' }) Button(`Click to increase count=${this.count}`) .margin(20) .onClick(() => { // Change the value of the internal status variable count. this.count += this.increaseBy }) } } } ``` ## @Prop **@Prop** and **@State** have the same semantics but different initialization modes. A **@Prop** decorated variable in a component must be initialized using the **@State** decorated variable in its parent component. The **@Prop** decorated variable can be modified in the component, but the modification is not updated to the parent component; the modification to the **@State** decorated variable is synchronized to the **@Prop** decorated variable. That is, **@Prop** establishes one-way data binding. The **@Prop** decorated state variable has the following features: - Support for simple types: The number, string, and boolean types are supported. - Private: Data is accessed only within the component. - Support for multiple instances: A component can have multiple attributes decorated by **@Prop**. - Support for initialization with a value passed to the @Prop decorated variable: When a new instance of the component is created, all **@Prop** variables must be initialized. Initialization inside the component is not supported. > **NOTE** > > A **@Prop** decorated variable cannot be initialized inside the component. **Example** In the preceding example, when the user presses **+1** or **-1**, the status of the parent component changes and the **build** method is executed again. In this case, a new **CountDownComponent** instance is created. The **countDownStartValue** attribute of the parent component is used to initialize the **@Prop** decorated variable of the child component. When the **count - costOfOneAttempt** button of the child component is touched, the value of the **@Prop** decorated variable **count** is changed. As a result, the **CountDownComponent** is rendered again. However, the change of the **count** value does not affect the **countDownStartValue** value of the parent component. ```ts // xxx.ets @Entry @Component struct ParentComponent { @State countDownStartValue: number = 10 // Initialize countDownStartValue build() { Column() { Text(`Grant ${this.countDownStartValue} nuggets to play.`).fontSize(18) Button('+1 - Nuggets in New Game') .margin(15) .onClick(() => { this.countDownStartValue += 1 }) Button('-1 - Nuggets in New Game') .margin(15) .onClick(() => { this.countDownStartValue -= 1 }) // When creating a child component, you must provide the initial value of its @Prop decorated variable count in the constructor parameter and initialize the regular variable costOfOneAttempt (not @Prop decorated). CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2 }) } } } @Component struct CountDownComponent { @Prop count: number private costOfOneAttempt: number build() { Column() { if (this.count > 0) { Text(`You have ${this.count} Nuggets left`).fontSize(18) } else { Text('Game over!').fontSize(18) } Button('count - costOfOneAttempt') .margin(15) .onClick(() => { this.count -= this.costOfOneAttempt }) } } } ``` ## @Link Two-way binding can be established between the **@Link** decorated variable and the **@State** decorated variable of the parent component. The **@Link** data has the following features: - Support for multiple types: The **@Link** decorated variables support the data types the same as the **@State** decorated variables; that is, the value can be of the following types: class, number, string, boolean, or arrays of these types. - Private: Data is accessed only within the component. - Single data source: The variable used to initialize the **@Link** decorated variable in a component must be a state variable defined in the parent component. - **Two-way binding**: When a child component changes the **@Link** decorated variable, the **@State** decorated variable of its parent component is also changed. - Support for initialization with the variable reference passed to the @Link decorated variable: When creating an instance of the component, you must use the naming parameter to initialize all **@Link** decorated variables. **@Link** decorated variables can be initialized by using the reference of the **@State** or **@Link** decorated variable. Wherein, the **@State** decorated variables can be referenced using the **'$'** operator. > **NOTE** > > A **@Link** decorated variable cannot be initialized inside the component. **Simple Type Example** The **@Link** semantics are derived from the '**$**' operator. In other words, **$isPlaying** is the two-way binding of the internal state **this.isPlaying**. When the button in the **PlayButton** child component is touched, the value of the **@Link** decorated variable is changed, and **PlayButton** together with the **\** and **\