State Management Overview

In previous examples, most of the pages built are static pages, which are delivered to the end user without having to be processed. If you are building dynamic, interactive pages, you need to master state management.

Figure 1 State managed UI

Video_2023-03-06_152548

In the preceding example, the interaction between the user and the application triggers an update in the text state, which in turn triggers re-rendering of the UI. As a result, the Hello World text changes to Hello ArkUI.

In the declarative UI framework, the UI is the execution result of the application state. You build a UI model in which the application runtime state is a parameter. When the parameter is changed, the UI as the return result is updated accordingly. This process of UI re-rendering caused by the application runtime state changes is called the state management mechanism in ArkUI.

Custom components have variables. A variable must be decorated by a decorator whenever the re-rendering of the UI depends on this variable. Otherwise, the UI is rendered only at initialization and will not be updated. The following figure shows the relationship between the state and view (UI).

en-us_image_0000001562352677

  • View (UI): UI rendering, which is visual representation of the UI description in the build method and @Builder decorated method.

  • State: data that drives the UI to re-render. State data is changed by invoking the event method of the component. The change of the state data triggers the re-rendering of the UI.

Basic Concepts

  • State variable: a variable decorated by a state decorator. Its value change will trigger UI re-renders. Example: @State num: number = 1, where @State is a state decorator and num is a state variable.

  • Regular variable: a variable that is not decorated by a state decorator and is usually used for auxiliary calculation. Its value change will not trigger UI re-renders. In the following example, the increaseBy variable is a regular variable.

  • Data source/Synchronization source: original source of a state variable, which can be synchronized to different state data. Generally, it is the data passed from the parent component to the child component. In the following example, the data source is count: 1.

  • Named parameter mechanism: a mechanism where the parent component passes state variables to the child component by specifying parameters. It is the primary means of passing synchronization parameters from the parent component to the child component. Example: CompA: ({ aProp: this.aProp }).

  • Initialization from the parent component: a process where the parent component uses the named parameter mechanism to pass specified parameters to the child component. The default value used in local initialization will be overwritten by the value passed from the parent component. Example:

    @Component
    struct MyComponent {
      @State count: number = 0;
      private increaseBy: number = 1;
    
      build() {
      }
    }
    
    @Component
    struct Parent {
      build() {
        Column() {
          // Initialization from the parent component: The named parameter specified here will overwrite the default value defined locally.
          MyComponent({ count: 1, increaseBy: 2 })
        }
      }
    }
    
  • Child component initialization: a capability to pass state variables to the child component to initialize the corresponding state variables therein. The example is the same as above.

  • Local initialization: a process where a value is assigned to a variable as its default value in the variable declaration. Example: @State count: number = 0.

Decorator Overview

ArkUI provides a diverse array of decorators. You can use these decorators to observe state variables changes within a component or globally and pass the changes between different component levels (for example, between parent and child components or grandparent and grandchild components). According to the scope of the state variable, decorators can be roughly classified into the following types:

  • Decorators for managing the state of a component: implement state management at the component level by allowing for observation of state changes within a component and changes at different component levels. The observation is limited to state changes in the same component tree, that is, on the same page.

  • Decorators for managing the state of an application: implement global state management of an application by allowing for observation of state changes on different pages or even different UIAbility components.

According to the data transfer mode and synchronization type, decorators can also be classified into the following types:

  • Decorators that allow for one-way (read-only) transfer

  • Decorators that allow for two-way (mutable) transfer

The following figure illustrates the decorators. For details, see Component State Management and Application State Management. You can use these decorators at your disposal to implement linkage between data and the UI.

en-us_image_0000001502704640

In the preceding figure, the decorators in the Components area are used for state management at the component level, while others are used for state management at the application level. You can use @StorageLink/@LocalStorageLink to implement two-way synchronization of the application and component state, and @StorageProp/@LocalStorageProp to implement one-way synchronization.

Decorators for component state management:

  • @State: An @State decorated variable holds the state of the owning component. It can be the source of one- or two-way synchronization with child components. When the variable changes, the dependent component will be updated.

  • @Prop: An @Prop decorated variable can create one-way synchronization with a variable of its parent component. @Prop decorated variables are mutable, but changes are not synchronized to the parent component.

  • @Link: An @Link decorated variable creates two-way synchronization with a variable of its parent component. When the @Link decorated variable has its value changed, its source is updated as well; when the source updates, the @Link decorated variable will do as well.

  • @Provide/@Consume: Variables decorated by @Provide/@Consume are used for data synchronization across component levels. The components can be bound to the variables through aliases or attribute names. Data does not need to be passed through the named parameter mechanism.

  • @Observed: @Observed is a class decorator. You can use it to decorate the class that has multiple levels of nested objects or arrays to be observed. Note that @Observed must be used with @ObjectLink for two-way synchronization or with @Prop for one-way synchronization.

  • @ObjectLink: An @ObjectLink decorated variable is used with an @Observed decorated class of the parent component for two-way data synchronization. It is applicable in scenarios involving multiple levels of nested objects or arrays in the class.

NOTE

Only @Observed/@ObjectLink can be used to observe changes of nested attributes. Other decorators can be used to observe changes of attributes at the first layer only. For details, see the "Observed Changes and Behavior" part in each decorator section.

Decorators for application state management:

  • AppStorage: a special LocalStorage singleton instance. It is an application-wide database bound to the application process and can be linked to components through the @StorageProp and @StorageLink decorators.

  • AppStorage is the hub for application state. Data that needs to interact with components (UI) is stored in AppStorage, including PersistentStorage and Environment data. The UI accesses the data through the decorators or APIs provided by AppStorage.

  • LocalStorage: an in-memory "database" for the application state declared by the application and typically used to share state across pages. It can be linked to the UI through the @LocalStorageProp and @LocalStorageLink decorators.

Other State Management Features

@Watch: listens for the changes of state variables.

$$operator: provides a TS variable by-reference to a built-in component so that the variable value and the internal state of that component are kept in sync.