• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# getTarget API: Obtaining Original Objects
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @jiyujia926-->
5<!--Designer: @s10021109-->
6<!--Tester: @TerryTsao-->
7<!--Adviser: @zhang_yixin13-->
8
9To obtain the original object before a proxy is added by the state management framework, you can use the [getTarget](../../reference/apis-arkui/js-apis-StateManagement.md#gettarget) API.
10
11Before reading this topic, you are advised to review [\@Observed](./arkts-observed-and-objectlink.md) and [\@ObservedV2](./arkts-new-observedV2-and-trace.md).
12
13>**NOTE**
14>
15>The **getTarget** API in UIUtils is supported since API version 12.
16
17## Overview
18
19The state management framework adds proxies to original objects of the class, Date, Map, Set, and Array types to observe attribute changes and API invoking. Proxies will change the variable types. In scenarios such as type determination and Node-API invoking, unexpected results may be generated because the variable type is not the type of the original object.
20
21- Import the UIUtils to use the **getTarget** API.
22
23  ```ts
24  import { UIUtils } from '@kit.ArkUI';
25  ```
26
27- In state management V1, proxies are added to the following to observe changes in top-level properties or changes triggered by API calls: (1) instances of classes decorated with \@Observed; (2) objects of the Class, Date, Map, Set, and Array types decorated with [\@State](./arkts-state.md) or other state variable decorators.
28- In state management V2, proxies are added to the following to observe changes triggered by API calls: objects of the Date, Map, Set, and Array types decorated with [\@Trace](./arkts-new-observedV2-and-trace.md), [\@Local](./arkts-new-local.md), or other state variable decorators.
29
30The **getTarget** API is used to obtain the original objects of these proxy objects.
31
32## Constraints
33
34- Only the parameters of the object type can be passed by **getTarget**.
35
36  ```ts
37  import { UIUtils } from '@kit.ArkUI';
38  let res = UIUtils.getTarget(2); // Incorrect usage. The input parameter is of the non-object type.
39  @Observed
40  class Info {
41    name: string = "Tom";
42  }
43  let info: Info = new Info();
44  let rawInfo: Info = UIUtils.getTarget (info); // Correct usage.
45  ```
46
47- Changes to the content in the original object obtained by **getTarget** cannot be observed nor trigger UI re-renders.
48
49  ```ts
50  import { UIUtils } from '@kit.ArkUI';
51  @Observed
52  class Info {
53    name: string = "Tom";
54  }
55  @Entry
56  @Component
57  struct Index {
58    @State info: Info = new Info();
59
60    build() {
61      Column() {
62        Text(`info.name: ${this.info.name}`)
63        Button(`Change Proxy Object Properties`)
64          .onClick(() => {
65            this.info.name = "Alice"; // The Text component can be re-rendered.
66          })
67        Button(`Change Original Object Properties`)
68          .onClick(() => {
69            let rawInfo: Info = UIUtils.getTarget(this.info);
70            rawInfo.name = "Bob"; // The Text component cannot be re-rendered.
71          })
72      }
73    }
74  }
75  ```
76
77## Use Scenarios
78
79### Obtaining the Original Object Before Proxy Addition in State Management V1
80
81State management V1 adds proxies to the following objects:
82
831. Instances of classes decorated with \@Observed A proxy is automatically added to an instance of a class decorated with \@Observed when the instance is created. However, instances not initialized with the **new** operator are not proxied.
84
85```ts
86@Observed
87class ObservedClass {
88  name: string = "Tom";
89}
90class NonObservedClass {
91  name: string = "Tom";
92}
93let observedClass: ObservedClass = new ObservedClass(); // Proxied.
94let nonObservedClass: NonObservedClass = new NonObservedClass(); // Not proxied.
95```
96
972. Complex-type objects decorated with state variable decorators Proxies are added to objects of the Class, Map, Set, Date, or Array type decorated with \@State, \@Prop, or other state variable decorators. If the object is already a proxy, no new proxy is added.
98
99```ts
100@Observed
101class ObservedClass {
102  name: string = "Tom";
103}
104class NonObservedClass {
105  name: string = "Tom";
106}
107let observedClass: ObservedClass = new ObservedClass(); // Proxied.
108let nonObservedClass: NonObservedClass = new NonObservedClass(); // Not proxied.
109@Entry
110@Component
111struct Index {
112  @State observedObject: ObservedClass = observedClass; // No new proxy is created (the object is already proxied).
113  @State nonObservedObject: NonObservedClass = nonObservedClass; // A proxy is created.
114  @State numberList: number[] = [1, 2, 3]; // A proxy is created for the Array type.
115  @State sampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // A proxy is created for the Map type.
116  @State sampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // A proxy is created for the Set type.
117  @State sampleDate: Date = new Date(); // A proxy is created for the Date type.
118
119  build() {
120    Column() {
121      Text(`this.observedObject === observedClass: ${this.observedObject === observedClass}`) // true
122      Text(`this.nonObservedObject === nonObservedClass: ${this.nonObservedObject === nonObservedClass}`) // false
123    }
124  }
125}
126```
127
128Use **UIUtils.getTarget** to obtain the original objects before proxies are added.
129
130```ts
131import { UIUtils } from '@kit.ArkUI';
132@Observed
133class ObservedClass {
134  name: string = "Tom";
135}
136class NonObservedClass {
137  name: string = "Tom";
138}
139let observedClass: ObservedClass = new ObservedClass(); // Proxied.
140let nonObservedClass: NonObservedClass = new NonObservedClass(); // Not proxied.
141let globalNumberList: number[] = [1, 2, 3]; // Not proxied.
142let globalSampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // Not proxied.
143let globalSampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // Not proxied.
144let globalSampleDate:Date = new Date (); // Not proxied.
145@Entry
146@Component
147struct Index {
148  @State observedObject: ObservedClass = observedClass; // No new proxy is created (the object is already proxied).
149  @State nonObservedObject: NonObservedClass = nonObservedClass; // A proxy is created.
150  @State numberList: number[] = globalNumberList; // A proxy is created for the Array type.
151  @State sampleMap: Map<number, string> = globalSampleMap; // A proxy is created for the Map type.
152  @State sampleSet: Set<number> = globalSampleSet; // A proxy is created for the Set type.
153  @State sampleDate: Date = globalSampleDate; // A proxy is created for the Date type.
154
155  build() {
156    Column() {
157      Text(`this.observedObject === observedClass: ${this.observedObject ===
158           observedClass}`) // true
159      Text(`UIUtils.getTarget(this.nonObservedObject) === nonObservedClass: ${UIUtils.getTarget(this.nonObservedObject) ===
160           nonObservedClass}`) // true
161      Text(`UIUtils.getTarget(this.numberList) === globalNumberList: ${UIUtils.getTarget(this.numberList) ===
162           globalNumberList}`) // true
163      Text(`UIUtils.getTarget(this.sampleMap) === globalSampleMap: ${UIUtils.getTarget(this.sampleMap) ===
164           globalSampleMap}`) // true
165      Text(`UIUtils.getTarget(this.sampleSet) === globalSampleSet: ${UIUtils.getTarget(this.sampleSet) ===
166           globalSampleSet}`) // true
167      Text(`UIUtils.getTarget(this.sampleDate) === globalSampleDate: ${UIUtils.getTarget(this.sampleDate) ===
168           globalSampleDate}`) // true
169    }
170  }
171}
172```
173
174### Obtaining the Original Object Before Proxy Addition in State Management V2
175
176In state management V2, proxies are added to objects of the Map, Set, Date, and Array type decorated with \@Trace, \@Local, or other state variable decorators. Unlike in state management V1, no proxies are added to class instances in state management V2.
177
178```ts
179@ObservedV2
180class ObservedClass {
181  @Trace name: string = "Tom";
182}
183let globalObservedObject: ObservedClass = new ObservedClass(); // Not proxied.
184let globalNumberList: number[] = [1, 2, 3]; // Not proxied.
185let globalSampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // Not proxied.
186let globalSampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // Not proxied.
187let globalSampleDate:Date = new Date (); // Not proxied.
188@Entry
189@ComponentV2
190struct Index {
191  @Local observedObject: ObservedClass = globalObservedObject; // Objects in V2 are not proxied.
192  @Local numberList: number[] = globalNumberList; // A proxy is created for the Array type.
193  @Local sampleMap: Map<number, string> = globalSampleMap; // A proxy is created for the Map type.
194  @Local sampleSet: Set<number> = globalSampleSet; // A proxy is created for the Set type.
195  @Local sampleDate: Date = globalSampleDate; // A proxy is created for the Date type.
196
197  build() {
198    Column() {
199      Text(`this.observedObject === globalObservedObject ${this.observedObject === globalObservedObject}`) // true
200      Text(`this.numberList === globalNumberList ${this.numberList === globalNumberList}`) // false
201    }
202  }
203}
204```
205
206Use **UIUtils.getTarget** to obtain the original objects before proxies are added.
207
208```ts
209import { UIUtils } from '@kit.ArkUI';
210@ObservedV2
211class ObservedClass {
212  @Trace name: string = "Tom";
213}
214let globalObservedObject: ObservedClass = new ObservedClass(); // Not proxied.
215let globalNumberList: number[] = [1, 2, 3]; // Not proxied.
216let globalSampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // Not proxied.
217let globalSampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // Not proxied.
218let globalSampleDate:Date = new Date (); // Not proxied.
219@Entry
220@ComponentV2
221struct Index {
222  @Local observedObject: ObservedClass = globalObservedObject; // Objects in V2 are not proxied.
223  @Local numberList: number[] = globalNumberList; // A proxy is created for the Array type.
224  @Local sampleMap: Map<number, string> = globalSampleMap; // A proxy is created for the Map type.
225  @Local sampleSet: Set<number> = globalSampleSet; // A proxy is created for the Set type.
226  @Local sampleDate: Date = globalSampleDate; // A proxy is created for the Date type.
227
228  build() {
229    Column() {
230      Text(`this.observedObject === globalObservedObject ${this.observedObject ===
231           globalObservedObject}`) // true
232      Text(`UIUtils.getTarget(this.numberList) === globalNumberList: ${UIUtils.getTarget(this.numberList) ===
233           globalNumberList}`) // true
234      Text(`UIUtils.getTarget(this.sampleMap) === globalSampleMap: ${UIUtils.getTarget(this.sampleMap) ===
235           globalSampleMap}`) // true
236      Text(`UIUtils.getTarget(this.sampleSet) === globalSampleSet: ${UIUtils.getTarget(this.sampleSet) ===
237           globalSampleSet}`) // true
238      Text(`UIUtils.getTarget(this.sampleDate) === globalSampleDate: ${UIUtils.getTarget(this.sampleDate) ===
239           globalSampleDate}`) // true
240    }
241  }
242}
243```
244
245In state management V2, decorators generate getter and setter methods for the decorated variables, and add the **\_\_ob\_** prefix to the original variable names. For performance purposes, the **getTarget** API does not process the prefix added by decorators in V2. Therefore, when an instance of a class decorated with \@ObservedV2 is passed to the **getTarget** API, the returned object remains the instance itself, and the property name decorated with \@Trace still has the **\_\_ob\_** prefix.
246
247This prefix causes some Node-APIs to fail to process object properties as expected.<br>Example:<br>Affected Node-APIs include the following:
248
249```ts
250// Class decorated with @ObservedV2.
251@ObservedV2
252class Info {
253  @Trace name: string = "Tom";
254  @Trace age: number = 24;
255}
256let info: Info = new Info(); // info instance passed in through Node-APIs.
257```
258
259| Name             | Result                                      |
260| ----------------------- | ---------------------------------------------- |
261| napi_get_property_names | Returns property names with the **\_\_ob\_** prefix, for example, **\_\_ob\_name** or **\_\_ob\_age**.       |
262| napi_set_property       | Changes values successfully using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**).      |
263| napi_get_property       | Obtains values using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**).      |
264| napi_has_property       | Returns **true** for both the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**).        |
265| napi_delete_property    | Requires the **\_\_ob\_** prefix for successful deletion.|
266| napi_has_own_property   | Returns **true** for both the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**).        |
267| napi_set_named_property | Changes values successfully using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**).      |
268| napi_get_named_property | Obtains values using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**).      |
269| napi_has_named_property | Returns **true** for both the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**).        |
270