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-->