← Back to list

HarmonyOSNext — V2()

Preface Previously, we discussed the decorators and key considerations for State Management V1, which are generally sufficient for most…

Lhj · 2025-05-20 06:48 · 0 claps · 2.6 min read
#harmony-next
Open on Medium ↗
Wiki topics: BIZ · Business Strategy

HarmonyOSNext — V2(1)

Preface Previously, we discussed the decorators and key considerations for State Management V1, which are generally sufficient for most development scenarios. However, there were still some areas of inconvenience, leading to the introduction of State Management V2. As of now, the V2 documentation has removed the “experimental” label, indicating it is stable for production use. The official recommendation is to migrate to V2 as soon as possible. Whether a V3 will be released in the future remains uncertain.

Overview The State Management V2 decorators, supported starting from API Level 12, include:

  • @ComponentV2: Defines custom components
  • @ObservedV2 and @Trace: Object observation
  • @Local: Manages internal component state
  • @Param: External input to components
  • @Once: One-time initialization synchronization
  • @Event: Standardizes component outputs
  • @Provider and @Consumer: Cross-level bidirectional synchronization
  • @Monitor: Listens for state variable changes
  • @Computed: Defines computed properties

@ComponentV2 Similar to V1’s @Component, @ComponentV2 decorates custom components. It has the following constraints:

  • Can only be used within classes decorated by @ComponentV2.
  • Works exclusively with other V2 state management decorators.
  • Mixing V1 and V2 decorators within the same component is not allowed.
@ComponentV2 
struct Index { 
  build() { 
  }
}

@ObservedV2 and @Trace Let’s start with these two decorators as they will be referenced when discussing other V2 features. These decorators enable deep observation, which means detecting changes in nested class properties. In V1, we used @Observed and @ObjectLink for this purpose, but they had a limitation: they could only observe property changes at the current level and not nested changes. With the combination of @ObservedV2 and @Trace in V2, you can now observe changes across multiple nested levels.

@ObservedV2
class Person {
  @Trace name: string = ''
  @Trace age: number = 0
  @Trace address:Address = new Address()
}

@ObservedV2
class Address{
  @Trace zipCode : string = '000000'
  @Trace city:string = 'beijing'
}

When defining a nested class, use the @ObservedV2 decorator on the class that needs to be observed, and use @Trace to decorate each property that participates in UI rendering. This can become quite cumbersome when there are many classes and properties to observe.

Another extremely inconvenient and troublesome issue is that instances of classes decorated with @ObservedV2 currently do not support serialization using JSON.stringify.

@Local

The variables decorated with this decorator can only be initialized locally and cannot be passed in from the outside. This is designed to better represent the internal state of the component without being affected by external parameters.

Compared with @State, it cannot observe the assignment of properties in class objects and can only observe the overall assignment of objects. That is to say, its observation capability is limited to the decorated variable itself.

When it is necessary to observe changes in the properties of class objects, you need to use the @ObservedV2 and @Trace decorators.

One thing to note is that in State Management V2, a proxy layer is added to Date, Map, Set, and Array decorated with state variable decorators such as @Trace and @Local to observe changes caused by API calls. Therefore, when comparing the values inside, you need to use UIUtils.getTarget() to obtain the original object for comparison.

list: string[][] = [['a'], ['b'], ['c']];
@Local strList: string[] = this.list[0];
@Monitor("strList")
onStrChange(monitor: IMonitor) {
    hilog.error(0x01, '@Local', 'strList has changed')
}

build() {
    Column() {
          Button('aa').onClick(() => {

        if (this.strList !== this.list[0]) {
          hilog.error(0x01, '@Local', 'aaa')
          this.strList = this.list[0];
        }
      })
      Button('bb').onClick(() => {

        if (UIUtils.getTarget(this.strList) !== this.list[0]) {
          hilog.error(0x01, '@Local', 'bb')
          this.strList = this.list[0];
        }
      })
    }
}

@Param

It can be passed in from the parent component or initialized locally. If used with @Require, the parent component must pass in this parameter, and the locally initialized value will be overwritten at this time.

One thing to note: you cannot directly modify the variable itself within the component, but you can modify the properties of the class object. If the properties of the class object are not decorated with @Trace, modifying the properties of the class object will not trigger a UI refresh.

When we directly modify the variable itself within the component, an error will be prompted: Cannot assign to ‘count’ because it is a read-only property.


메타데이터
post_id
8000e83083c8
slug
harmonyosnext-v2-8000e83083c8
url
https://medium.com/@lhj18250199598/harmonyosnext-v2-8000e83083c8
canonical_url
https://medium.com/@lhj18250199598/harmonyosnext-v2-8000e83083c8
author_url
https://medium.com/@lhj18250199598
status
ok
fetched_at
2026-07-25 17:06:40