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