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