DEV Community

HarmonyOS
HarmonyOS

Posted on

State Management V2 in ArkTS : Observing Class Property Changes

Read the original article:State Management V2 in ArkTS : Observing Class Property Changes

cke_1629.png

State Management V2 in ArkTS : Observing Class Property Changes

Introduction

When developing mobile apps, handling state properly is one of those things that can make or break the user experience. ArkTS has made this easier and more powerful with State Management V2. Thanks to features like @ObservedV2 and @Trace, working with the state feels more natural, organized, and easier to follow.

In this article, I’ll walk you through how these new tools improve on what we had in State Management V1. I’ll also share how you can use them in your projects with practical code examples and tips.

If you’ve worked in the Mobile Ecosystem or you’re just starting with ArkTS, this guide will help you write cleaner, more responsive, and easier-to-debug apps using the latest tools ArkTS has to offer.

What is a State?

In simple terms, state refers to the data that determines what your app looks like and how it behaves at a given moment. It can be anything from a user’s login status, the value of a text input, the current page in a navigation flow, to whether a button is enabled or disabled.

Whenever this data changes, the UI usually needs to reflect those changes. That’s where state management comes in — it’s all about how we store, update, and react to those changes in a clean and predictable way.

What are the benefits of State Management V2?

With state management V1, properties of nested class objects are not directly observable.

@Observed
class Father {
  son: Son;

  constructor(name: string, age: number) {
    this.son = new Son(name, age);
  }
}
@Observed
class Son {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
@Entry
@Component
struct Index {
  @State father: Father = new Father("John", 8);

  build() {
    Row() {
      Column() {
        Text(`name: ${this.father.son.name} age: ${this.father.son.age}`)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(() => {
            this.father.son.age++;
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

In the preceding example, clicking the Text component increases the value of age, but does not trigger UI re-renders.

How do @ObservedV2 and @Trace work?

With State Management v2, when you use @ObservedV2 along with @Trace, the properties decorated with @Trace become observable. That means any changes to those properties automatically trigger a UI re-render, keeping the interface in sync with the underlying data.

1️⃣ Define an Observable Class

@ObservedV2
class Son {
  @Trace age: number = 100;
}
Enter fullscreen mode Exit fullscreen mode

2️⃣ Nesting Observable Data

class Father {
  son: Son = new Son();
}
Enter fullscreen mode Exit fullscreen mode

3️⃣ Build the Component

@Entry
@Component
struct Index {
  father: Father = new Father();
Enter fullscreen mode Exit fullscreen mode

4️⃣ UI Binding

build() {
    Column() {
      // If age is changed, the Text component is re-rendered.
      Text(`${this.father.son.age}`)
        .onClick(() => {
          this.father.son.age++;
        })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

  • The Text component displays father.son.age.
  • When you click the text, age is incremented.
  • Since age is @Trace-decorated and inside an @ObservedV2 class, a change will be detected and automatically re-renders the UI.

🎯 No manual refresh needed. No boilerplate code. Just reactive, clean, and efficient.

References

Written by Egemen Ayhan

Top comments (0)