1# \@Link Decorator: Two-Way Synchronization Between Parent and Child Components 2 3 4An \@Link decorated variable creates two-way synchronization with a variable of its parent component. 5 6Before reading this topic, you are advised to understand the basic usage of [\@State](./arkts-state.md). 7 8> **NOTE** 9> 10> This decorator can be used in ArkTS widgets since API version 9. 11> 12> This decorator can be used in atomic services since API version 11. 13 14## Overview 15 16An \@Link decorated variable in a child component shares the same value with a variable in its parent component. 17 18 19## Rules of Use 20 21| \@Link Decorator | Description | 22| ---------------------------------------- | ------------------------------------------------------------ | 23| Decorator parameters | None. | 24| Synchronization type | Two-way:<br>The state variable in the parent component can be synchronized with the child component \@Link in a two-way manner. When one of them changes, the other can sense the change. | 25| Allowed variable types | Object, class, string, number, Boolean, enum, and array of these types.<br>Date type.<br>(Applicable to API version 11 or later) Map and Set types.<br>The union types defined by the ArkUI framework, including Length, ResourceStr, and ResourceColor, are supported.<br>The type must be specified and must be the same as that of the counterpart variable of the parent component.<br>For details about the scenarios of supported types, see [Observed Changes](#observed-changes).<br>**any** is not supported.<br>(Applicable to API version 11 and later versions) Union type of the preceding types, for example, **string \| number**, **string \| undefined** or **ClassA \| null**. For details, see [Union Type @Link](#union-type-link).<br>**NOTE**<br>When **undefined** or **null** is used, you are advised to explicitly specify the type to pass the TypeScript type check. For example, **@Link a: string \| undefined = undefined**. | 26| Initial value for the decorated variable | Forbidden. | 27 28 29## Variable Transfer/Access Rules 30 31| Transfer/Access | Description | 32| ---------- | ---------------------------------------- | 33| Initialization and update from the parent component| Mandatory. A two-way synchronization relationship can be established with the @State, @StorageLink, or \@Link decorated variable in the parent component. An @Link decorated variable can be initialized from an [\@State](./arkts-state.md), @Link, [\@Prop](./arkts-prop.md), [\@Provide](./arkts-provide-and-consume.md), [\@Consume](./arkts-provide-and-consume.md), [\@ObjectLink](./arkts-observed-and-objectlink.md), [\@StorageLink](./arkts-appstorage.md#storagelink), [\@StorageProp](./arkts-appstorage.md#storageprop), [\@LocalStorageLink](./arkts-localstorage.md#localstoragelink), or [\@LocalStorageProp](./arkts-localstorage.md#localstorageprop) decorated variable in the parent component.<br>Since API version 9, the syntax is **Comp({ aLink: this.aState })** for initializing an \@Link decorated variable in the child component from an @State decorated variable in its parent component. The **Comp({aLink: $aState})** syntax is also supported.| 34| Child component initialization | Supported; can be used to initialize a regular variable or \@State, \@Link, \@Prop, or \@Provide decorated variable in the child component.| 35| Access | Private, accessible only within the component. | 36 37 **Figure 1** Initialization rule 38 39 40 41 42## Observed Changes and Behavior 43 44 45### Observed Changes 46 47- When the decorated variable is of the Boolean, string, or number type, its value change can be observed. For details, see [Example for @Link with Simple and Class Types](#example-for-link-with-simple-and-class-types). 48 49- When the decorated variable is of the class or Object type, its value change and value changes of all its attributes, that is, the attributes that **Object.keys(observedObject)** returns, can be observed. For details, see [Example for @Link with Simple and Class Types](#example-for-link-with-simple-and-class-types). 50 51- When the decorated variable is of the array type, the addition, deletion, and updates of array items can be observed. For details, see [Array Type \@Link](#array-type-link). 52 53- When the decorated variable is of the Date type, the overall value assignment of the Date object can be observed, and the following APIs can be called to update Date attributes: **setFullYear**, **setMonth**, **setDate**, **setHours**, **setMinutes**, **setSeconds**, **setMilliseconds**, **setTime**, **setUTCFullYear**, **setUTCMonth**, **setUTCDate**, **setUTCHours**, **setUTCMinutes**, **setUTCSeconds**, and **setUTCMilliseconds**. 54 55```ts 56@Component 57struct DateComponent { 58 @Link selectedDate: Date; 59 60 build() { 61 Column() { 62 Button(`child increase the year by 1`).onClick(() => { 63 this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1) 64 }) 65 Button('child update the new date') 66 .margin(10) 67 .onClick(() => { 68 this.selectedDate = new Date('2023-09-09') 69 }) 70 DatePicker({ 71 start: new Date('1970-1-1'), 72 end: new Date('2100-1-1'), 73 selected: this.selectedDate 74 }) 75 } 76 77 } 78} 79 80@Entry 81@Component 82struct ParentComponent { 83 @State parentSelectedDate: Date = new Date('2021-08-08'); 84 85 build() { 86 Column() { 87 Button('parent increase the month by 1') 88 .margin(10) 89 .onClick(() => { 90 this.parentSelectedDate.setMonth(this.parentSelectedDate.getMonth() + 1) 91 }) 92 Button('parent update the new date') 93 .margin(10) 94 .onClick(() => { 95 this.parentSelectedDate = new Date('2023-07-07') 96 }) 97 DatePicker({ 98 start: new Date('1970-1-1'), 99 end: new Date('2100-1-1'), 100 selected: this.parentSelectedDate 101 }) 102 103 DateComponent({ selectedDate:this.parentSelectedDate }) 104 } 105 } 106} 107``` 108 109- When the decorated variable is **Map**, value changes of **Map** can be observed. In addition, you can call the **set**, **clear**, and **delete** APIs of **Map** to update its value. For details, see [Decorating Variables of the Map Type](#decorating-variables-of-the-map-type). 110 111- When the decorated variable is **Set**, value changes of **Set** can be observed. In addition, you can call the **add**, **clear**, and **delete** APIs of **Set** to update its value. For details, see [Decorating Variables of the Set Type](#decorating-variables-of-the-set-type). 112 113### Framework Behavior 114 115An \@Link decorated variable shares the lifecycle of its owning component. 116 117To understand the value initialization and update mechanism of the \@Link decorated variable, it is necessary to consider the parent component and the initial render and update process of the child component that owns the \@Link decorated variable (in this example, the \@State decorated variable in the parent component is used). 118 1191. Initial render: The execution of the parent component's **build()** function creates an instance of the child component. The initialization process is as follows: 120 1. An \@State decorated variable of the parent component must be specified to initialize the child component's \@Link decorated variable. The child component's \@Link decorated variable value and its source variable are kept in sync (two-way data synchronization). 121 2. The \@State state variable wrapper class of the parent component is passed to the child component through the build function. After obtaining the \@State state variable of the parent component, the \@Link wrapper class of the child component registers the **this** pointer to the current \@Link wrapper class with the \@State variable of the parent component. 122 1232. Update of the \@Link source: When the state variable in the parent component is updated, the \@Link decorated variable in the related child component is updated. Processing steps: 124 1. As indicated in the initial rendering step, the child component's \@Link wrapper class registers the current **this** pointer with the parent component. When the \@State decorated variable in the parent component is changed, all system components (**elementid**) and state variables (such as the \@Link wrapper class) that depend on the parent component are traversed and updated. 125 2. After the \@Link wrapper class is updated, all system components (**elementId**) that depend on the \@Link decorated variable in the child component are notified of the update. In this way, the parent component has the state data of the child components synchronized. 126 1273. Update of \@Link: After the \@Link decorated variable in the child component is updated, the following steps are performed (the \@State decorated variable in the parent component is used): 128 1. After the \@Link decorated variable is updated, the **set** method of the \@State wrapper class in the parent component is called to synchronize the updated value back to the parent component. 129 2. The \@Link in the child component and \@State in the parent component traverse the dependent system components and update the corresponding UI. In this way, the \@Link decorated variable in the child component is synchronized back to the \@State decorated variable in the parent component. 130 131 132## Restrictions 133 1341. The @Link decorator cannot be used in custom components decorated by [\@Entry](https://gitee.com/openharmony/docs/blob/master/en/application-dev/quick-start/arkts-create-custom-components.md#basic-structure-of-a-custom-component). 135 1362. Do not initialize variables decorated by \@Link locally. Otherwise, an error will be reported during compilation. 137 138```ts 139// Incorrect format. An error is reported during compilation. 140@Link count: number = 10; 141 142// Correct format. 143@Link count: number; 144``` 145 1463. The type of the variable decorated by \@Link must be the same as the data source type. Otherwise, the framework throws a runtime error. 147 148[Incorrect Example] 149 150```ts 151class Info { 152 info: string = 'Hello'; 153} 154 155class Cousin { 156 name: string = 'Hello'; 157} 158 159@Component 160struct Child { 161 // Incorrect format. The data source types of @Link and @State are different. 162 @Link test: Cousin; 163 164 build() { 165 Text(this.test.name) 166 } 167} 168 169@Entry 170@Component 171struct LinkExample { 172 @State info: Info = new Info(); 173 174 build() { 175 Column() { 176 // Incorrect format. The data source types of @Link and @State are different. 177 Child({test: new Cousin()}) 178 } 179 } 180} 181``` 182 183[Correct Example] 184 185```ts 186class Info { 187 info: string = 'Hello'; 188} 189 190@Component 191struct Child { 192 // Correct format. 193 @Link test: Info; 194 195 build() { 196 Text(this.test.info) 197 } 198} 199 200@Entry 201@Component 202struct LinkExample { 203 @State info: Info = new Info(); 204 205 build() { 206 Column() { 207 // Correct format. 208 Child({test: this.info}) 209 } 210 } 211} 212``` 213 2144. \@Link decorated variables can be initialized only by state variables. Initializing the variables using constants will cause a warn alarm during compilation, and an error "is not callable" is reported during runtime. 215 216[Incorrect Example] 217 218```ts 219class Info { 220 info: string = 'Hello'; 221} 222 223@Component 224struct Child { 225 @Link msg: string; 226 @Link info: string; 227 228 build() { 229 Text(this.msg + this.info) 230 } 231} 232 233@Entry 234@Component 235struct LinkExample { 236 @State message: string = 'Hello'; 237 @State info: Info = new Info(); 238 239 build() { 240 Column() { 241 // Incorrect format. Common variables cannot initialize the @Link decorated variables. 242 Child({msg: 'World', info: this.info.info}) 243 } 244 } 245} 246``` 247 248[Correct Example] 249 250```ts 251class Info { 252 info: string = 'Hello'; 253} 254 255@Component 256struct Child { 257 @Link msg: string; 258 @Link info: Info; 259 260 build() { 261 Text(this.msg + this.info.info) 262 } 263} 264 265@Entry 266@Component 267struct LinkExample { 268 @State message: string = 'Hello'; 269 @State info: Info = new Info(); 270 271 build() { 272 Column() { 273 // Correct format. 274 Child({msg: this.message, info: this.info}) 275 } 276 } 277} 278``` 279 2805. \@Link cannot decorate variables of the function type. Otherwise, the framework throws a runtime error. 281 282 283## Usage Scenarios 284 285 286### Example for @Link with Simple and Class Types 287 288In the following example, after **Parent View: Set yellowButton** and **Parent View: Set GreenButton** of the parent component **ShufflingContainer** are clicked, the change in the parent component is synchronized to the child components. 289 290 1. After buttons of the child components **GreenButton** and **YellowButton** are clicked, the child components (@Link decorated variables) change accordingly. Due to the two-way synchronization relationship between @Link and @State, the changes are synchronized to the parent component. 291 292 2. When a button in the parent component **ShufflingContainer** is clicked, the parent component (@State decorated variable) changes, and the changes are synchronized to the child components, which are then updated accordingly. 293 294```ts 295class GreenButtonState { 296 width: number = 0; 297 298 constructor(width: number) { 299 this.width = width; 300 } 301} 302 303@Component 304struct GreenButton { 305 @Link greenButtonState: GreenButtonState; 306 307 build() { 308 Button('Green Button') 309 .width(this.greenButtonState.width) 310 .height(40) 311 .backgroundColor('#64bb5c') 312 .fontColor('#FFFFFF, 90%') 313 .onClick(() => { 314 if (this.greenButtonState.width < 700) { 315 // Update the attribute of the class. The change can be observed and synchronized back to the parent component. 316 this.greenButtonState.width += 60; 317 } else { 318 // Update the class. The change can be observed and synchronized back to the parent component. 319 this.greenButtonState = new GreenButtonState(180); 320 } 321 }) 322 } 323} 324 325@Component 326struct YellowButton { 327 @Link yellowButtonState: number; 328 329 build() { 330 Button('Yellow Button') 331 .width(this.yellowButtonState) 332 .height(40) 333 .backgroundColor('#f7ce00') 334 .fontColor('#FFFFFF, 90%') 335 .onClick(() => { 336 // The change of the decorated variable of a simple type in the child component can be synchronized back to the parent component. 337 this.yellowButtonState += 40.0; 338 }) 339 } 340} 341 342@Entry 343@Component 344struct ShufflingContainer { 345 @State greenButtonState: GreenButtonState = new GreenButtonState(180); 346 @State yellowButtonProp: number = 180; 347 348 build() { 349 Column() { 350 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) { 351 // Simple type @Link in the child component synchronized from @State in the parent component. 352 Button('Parent View: Set yellowButton') 353 .width(312) 354 .height(40) 355 .margin(12) 356 .fontColor('#FFFFFF, 90%') 357 .onClick(() => { 358 this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 40 : 100; 359 }) 360 // Class type @Link in the child component synchronized from @State in the parent component. 361 Button('Parent View: Set GreenButton') 362 .width(312) 363 .height(40) 364 .margin(12) 365 .fontColor('#FFFFFF, 90%') 366 .onClick(() => { 367 this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100; 368 }) 369 // Initialize the class type @Link. 370 GreenButton({ greenButtonState: $greenButtonState }).margin(12) 371 // Initialize the simple type @Link. 372 YellowButton({ yellowButtonState: $yellowButtonProp }).margin(12) 373 } 374 } 375 } 376} 377``` 378 379 380 381### Array Type \@Link 382 383 384```ts 385@Component 386struct Child { 387 @Link items: number[]; 388 389 build() { 390 Column() { 391 Button(`Button1: push`) 392 .margin(12) 393 .width(312) 394 .height(40) 395 .fontColor('#FFFFFF, 90%') 396 .onClick(() => { 397 this.items.push(this.items.length + 1); 398 }) 399 Button(`Button2: replace whole item`) 400 .margin(12) 401 .width(312) 402 .height(40) 403 .fontColor('#FFFFFF, 90%') 404 .onClick(() => { 405 this.items = [100, 200, 300]; 406 }) 407 } 408 } 409} 410 411@Entry 412@Component 413struct Parent { 414 @State arr: number[] = [1, 2, 3]; 415 416 build() { 417 Column() { 418 Child({ items: $arr }) 419 .margin(12) 420 ForEach(this.arr, 421 (item: number) => { 422 Button(`${item}`) 423 .margin(12) 424 .width(312) 425 .height(40) 426 .backgroundColor('#11a2a2a2') 427 .fontColor('#e6000000') 428 }, 429 (item: ForEachInterface) => item.toString() 430 ) 431 } 432 } 433} 434``` 435 436 437 438As described above, the ArkUI framework can observe the addition, deletion, and replacement of array items. It should be noted that, in the preceding example, the type of the \@Link and \@State decorated variables is the same: number[]. It is not allowed to define the \@Link decorated variable in the child component as type number (**\@Link item: number**), and create child components for each array item in the \@State decorated array in the parent component. [\@Prop](arkts-prop.md) or [\@Observed](./arkts-observed-and-objectlink.md) should be used depending on application semantics. 439 440### Decorating Variables of the Map Type 441 442> **NOTE** 443> 444> Since API version 11, \@Link supports the Map type. 445 446In this example, the **value** variable is of the Map<number, string> type. When the button is clicked, the value of **message** changes, and the UI is re-rendered. 447 448```ts 449@Component 450struct Child { 451 @Link value: Map<number, string> 452 453 build() { 454 Column() { 455 ForEach(Array.from(this.value.entries()), (item: [number, string]) => { 456 Text(`${item[0]}`).fontSize(30) 457 Text(`${item[1]}`).fontSize(30) 458 Divider() 459 }) 460 Button('child init map').onClick(() => { 461 this.value = new Map([[0, "a"], [1, "b"], [3, "c"]]) 462 }) 463 Button('child set new one').onClick(() => { 464 this.value.set(4, "d") 465 }) 466 Button('child clear').onClick(() => { 467 this.value.clear() 468 }) 469 Button('child replace the first one').onClick(() => { 470 this.value.set(0, "aa") 471 }) 472 Button('child delete the first one').onClick(() => { 473 this.value.delete(0) 474 }) 475 } 476 } 477} 478 479 480@Entry 481@Component 482struct MapSample { 483 @State message: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]) 484 485 build() { 486 Row() { 487 Column() { 488 Child({ value: this.message }) 489 } 490 .width('100%') 491 } 492 .height('100%') 493 } 494} 495``` 496 497### Decorating Variables of the Set Type 498 499> **NOTE** 500> 501> Since API version 11, \@Link supports the Set type. 502 503In this example, the **message** variable is of the Set\<number\> type. When the button is clicked, the value of **message** changes, and the UI is re-rendered. 504 505```ts 506@Component 507struct Child { 508 @Link message: Set<number> 509 510 build() { 511 Column() { 512 ForEach(Array.from(this.message.entries()), (item: [number, string]) => { 513 Text(`${item[0]}`).fontSize(30) 514 Divider() 515 }) 516 Button('init set').onClick(() => { 517 this.message = new Set([0, 1, 2, 3, 4]) 518 }) 519 Button('set new one').onClick(() => { 520 this.message.add(5) 521 }) 522 Button('clear').onClick(() => { 523 this.message.clear() 524 }) 525 Button('delete the first one').onClick(() => { 526 this.message.delete(0) 527 }) 528 } 529 .width('100%') 530 } 531} 532 533 534@Entry 535@Component 536struct SetSample { 537 @State message: Set<number> = new Set([0, 1, 2, 3, 4]) 538 539 build() { 540 Row() { 541 Column() { 542 Child({ message: this.message }) 543 } 544 .width('100%') 545 } 546 .height('100%') 547 } 548} 549``` 550 551### Using Two-Way Synchronization Mechanism to Change Local Variables 552 553Use [\@Watch](./arkts-watch.md) to change local variables during two-way synchronization. 554 555In the following example, the \@State decorated variable **sourceNumber** is modified in \@Watch of \@Link to implement variable synchronization between parent and child components. However, the local modification of the \@State decorated variable **memberMessage** does not affect the variable change in the parent component. 556 557```ts 558@Entry 559@Component 560struct Parent { 561 @State sourceNumber: number = 0; 562 563 build() { 564 Column() { 565 Text(`sourceNumber of the parent component: ` + this.sourceNumber) 566 Child({ sourceNumber: this.sourceNumber }) 567 Button('sourceNumber is changed in the parent component') 568 .onClick(() => { 569 this.sourceNumber++; 570 }) 571 } 572 .width('100%') 573 .height('100%') 574 } 575} 576 577@Component 578struct Child { 579 @State memberMessage: string = 'Hello World'; 580 @Link @Watch('onSourceChange') sourceNumber: number; 581 582 onSourceChange() { 583 this.memberMessage = this.sourceNumber.toString(); 584 } 585 586 build() { 587 Column() { 588 Text(this.memberMessage) 589 Text(`sourceNumber of the child component: ` + this.sourceNumber.toString()) 590 Button('memberMessage is changed in the child component') 591 .onClick(() => { 592 this.memberMessage = 'Hello memberMessage'; 593 }) 594 } 595 } 596} 597``` 598 599## Union Type @Link 600 601@Link supports **undefined**, **null**, and union types. In the following example, the type of **name** is string | undefined. If the attribute or type of **name** is changed when the button in the parent component **Index** is clicked, the change will be synced to the child component. 602 603```ts 604@Component 605struct Child { 606 @Link name: string | undefined 607 608 build() { 609 Column() { 610 611 Button('Child change name to Bob') 612 .onClick(() => { 613 this.name = "Bob" 614 }) 615 616 Button('Child change name to undefined') 617 .onClick(() => { 618 this.name = undefined 619 }) 620 621 }.width('100%') 622 } 623} 624 625@Entry 626@Component 627struct Index { 628 @State name: string | undefined = "mary" 629 630 build() { 631 Column() { 632 Text(`The name is ${this.name}`).fontSize(30) 633 634 Child({ name: this.name }) 635 636 Button('Parents change name to Peter') 637 .onClick(() => { 638 this.name = "Peter" 639 }) 640 641 Button('Parents change name to undefined') 642 .onClick(() => { 643 this.name = undefined 644 }) 645 } 646 } 647} 648``` 649 650## FAQs 651 652### Incorrect Type of \@Link Decorated State Variable 653 654When using \@Link to decorate a state variable in a child component, ensure that the variable type is the same as the source type, and the source is a state variable decorated by a decorator such as \@State. 655 656[Incorrect Example] 657 658```ts 659@Observed 660class Info { 661 public age: number = 0; 662 663 constructor(age: number) { 664 this.age = age; 665 } 666} 667 668@Component 669struct LinkChild { 670 @Link testNum: number; 671 672 build() { 673 Text(`LinkChild testNum ${this.testNum}`) 674 } 675} 676 677@Entry 678@Component 679struct Parent { 680 @State info: Info = new Info(1); 681 682 build() { 683 Column() { 684 Text(`Parent testNum ${this.info.age}`) 685 .onClick(() => { 686 this.info.age += 1; 687 }) 688 // The type of the @Link decorated variable must be the same as that of the @State decorated data source. 689 LinkChild({ testNum: this.info.age }) 690 } 691 } 692} 693``` 694 695In the example, the type of **\@Link testNum: number** and the initialization from the parent component **LinkChild({testNum:this.info.age})** are incorrect. The data source of \@Link must be a decorated state variable. The \@Link decorated variables must be of the same type as the data source, for example, \@Link: T and \@State: T. Therefore, the value should be changed to **\@Link testNum: Info**, and the initialization from the parent component should be **LinkChild({testNum: this.info})**. 696 697[Correct Example] 698 699```ts 700@Observed 701class Info { 702 public age: number = 0; 703 704 constructor(age: number) { 705 this.age = age; 706 } 707} 708 709@Component 710struct LinkChild { 711 @Link testNum: Info; 712 713 build() { 714 Text(`LinkChild testNum ${this.testNum?.age}`) 715 .onClick(() => { 716 this.testNum.age += 1; 717 }) 718 } 719} 720 721@Entry 722@Component 723struct Parent { 724 @State info: Info = new Info(1); 725 726 build() { 727 Column() { 728 Text(`Parent testNum ${this.info.age}`) 729 .onClick(() => { 730 this.info.age += 1; 731 }) 732 // The type of the @Link decorated variable must be the same as that of the @State decorated data source. 733 LinkChild({ testNum: this.info }) 734 } 735 } 736} 737``` 738 739### Using the a.b(this.object) Format Fails to Trigger UI Re-render 740 741In the **build** method, when the variable decorated by @Link is of the object type and is called using the **a.b(this.object)** format, the native object of **this.object** is passed in the b method. If the property of **this.object** is changed, the UI cannot be re-rendered. In the following example, when the static method **Score.changeScore1** or **this.changeScore2** is used to change **this.score.value** in the **Child** component, the UI is not re-rendered. 742 743[Incorrect Example] 744 745```ts 746class Score { 747 value: number; 748 constructor(value: number) { 749 this.value = value; 750 } 751 752 static changeScore1(score:Score) { 753 score.value += 1; 754 } 755} 756 757@Entry 758@Component 759struct Parent { 760 @State score: Score = new Score(1); 761 762 build() { 763 Column({space:8}) { 764 Text(`The value in Parent is ${this.score.value}.`) 765 .fontSize(30) 766 .fontColor(Color.Red) 767 Child({ score: this.score }) 768 } 769 .width('100%') 770 .height('100%') 771 } 772} 773 774@Component 775struct Child { 776 @Link score: Score; 777 778 changeScore2(score:Score) { 779 score.value += 2; 780 } 781 782 build() { 783 Column({space:8}) { 784 Text(`The value in Child is ${this.score.value}.`) 785 .fontSize(30) 786 Button(`changeScore1`) 787 .onClick(()=>{ 788 // The UI cannot be re-rendered using a static method. 789 Score.changeScore1(this.score); 790 }) 791 Button(`changeScore2`) 792 .onClick(()=>{ 793 // The UI cannot be re-rendered using this. 794 this.changeScore2(this.score); 795 }) 796 } 797 } 798} 799``` 800 801You can add a proxy for **this.score** to re-render the UI by assigning a value to the variable and then calling the variable. 802 803[Correct Example] 804 805```ts 806class Score { 807 value: number; 808 constructor(value: number) { 809 this.value = value; 810 } 811 812 static changeScore1(score:Score) { 813 score.value += 1; 814 } 815} 816 817@Entry 818@Component 819struct Parent { 820 @State score: Score = new Score(1); 821 822 build() { 823 Column({space:8}) { 824 Text(`The value in Parent is ${this.score.value}.`) 825 .fontSize(30) 826 .fontColor(Color.Red) 827 Child({ score: this.score }) 828 } 829 .width('100%') 830 .height('100%') 831 } 832} 833 834@Component 835struct Child { 836 @Link score: Score; 837 838 changeScore2(score:Score) { 839 score.value += 2; 840 } 841 842 build() { 843 Column({space:8}) { 844 Text(`The value in Child is ${this.score.value}.`) 845 .fontSize(30) 846 Button(`changeScore1`) 847 .onClick(()=>{ 848 // Add a proxy by assigning a value. 849 let score1 = this.score; 850 Score.changeScore1(score1); 851 }) 852 Button(`changeScore2`) 853 .onClick(()=>{ 854 // Add a proxy by assigning a value. 855 let score2 = this.score; 856 this.changeScore2(score2); 857 }) 858 } 859 } 860} 861``` 862 863<!--no_check--> 864