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**.| 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`) 63 .onClick(() => { 64 this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1); 65 }) 66 Button('child update the new date') 67 .margin(10) 68 .onClick(() => { 69 this.selectedDate = new Date('2023-09-09'); 70 }) 71 DatePicker({ 72 start: new Date('1970-1-1'), 73 end: new Date('2100-1-1'), 74 selected: this.selectedDate 75 }) 76 } 77 78 } 79} 80 81@Entry 82@Component 83struct ParentComponent { 84 @State parentSelectedDate: Date = new Date('2021-08-08'); 85 86 build() { 87 Column() { 88 Button('parent increase the month by 1') 89 .margin(10) 90 .onClick(() => { 91 this.parentSelectedDate.setMonth(this.parentSelectedDate.getMonth() + 1); 92 }) 93 Button('parent update the new date') 94 .margin(10) 95 .onClick(() => { 96 this.parentSelectedDate = new Date('2023-07-07'); 97 }) 98 DatePicker({ 99 start: new Date('1970-1-1'), 100 end: new Date('2100-1-1'), 101 selected: this.parentSelectedDate 102 }) 103 104 DateComponent({ selectedDate:this.parentSelectedDate }) 105 } 106 } 107} 108``` 109 110- 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). 111 112- 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). 113 114### Framework Behavior 115 116An \@Link decorated variable shares the lifecycle of its owning component. 117 118To 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). 119 1201. Initial render: The execution of the parent component's **build()** creates an instance of the child component. The initialization process is as follows: 121 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). 122 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. 123 1242. 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: 125 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. 126 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. 127 1283. 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): 129 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. 130 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. 131 132 133## Constraints 134 1351. 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). 136 1372. Do not initialize variables decorated by \@Link locally. Otherwise, an error will be reported during compilation. 138 139 ```ts 140 // Incorrect format. An error is reported during compilation. 141 @Link count: number = 10; 142 143 // Correct format. 144 @Link count: number; 145 ``` 146 1473. The type of the variable decorated by \@Link must be the same as the data source type. Otherwise, the framework throws a runtime error. 148 149 [Incorrect Example] 150 151 ```ts 152 class Info { 153 info: string = 'Hello'; 154 } 155 156 class Cousin { 157 name: string = 'Hello'; 158 } 159 160 @Component 161 struct Child { 162 // Incorrect format. The data source types of @Link and @State are different. 163 @Link test: Cousin; 164 165 build() { 166 Text(this.test.name) 167 } 168 } 169 170 @Entry 171 @Component 172 struct LinkExample { 173 @State info: Info = new Info(); 174 175 build() { 176 Column() { 177 // Incorrect format. The data source types of @Link and @State are different. 178 Child({test: new Cousin()}) 179 } 180 } 181 } 182 ``` 183 184 [Correct Example] 185 186 ```ts 187 class Info { 188 info: string = 'Hello'; 189 } 190 191 @Component 192 struct Child { 193 // Correct format. 194 @Link test: Info; 195 196 build() { 197 Text(this.test.info) 198 } 199 } 200 201 @Entry 202 @Component 203 struct LinkExample { 204 @State info: Info = new Info(); 205 206 build() { 207 Column() { 208 // Correct format. 209 Child({test: this.info}) 210 } 211 } 212 } 213 ``` 214 2154. \@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. 216 217 [Incorrect Example] 218 219 ```ts 220 class Info { 221 info: string = 'Hello'; 222 } 223 224 @Component 225 struct Child { 226 @Link msg: string; 227 @Link info: string; 228 229 build() { 230 Text(this.msg + this.info) 231 } 232 } 233 234 @Entry 235 @Component 236 struct LinkExample { 237 @State message: string = 'Hello'; 238 @State info: Info = new Info(); 239 240 build() { 241 Column() { 242 // Incorrect format. Common variables cannot initialize the @Link decorated variables. 243 Child({msg: 'World', info: this.info.info}) 244 } 245 } 246 } 247 ``` 248 249 [Correct Example] 250 251 ```ts 252 class Info { 253 info: string = 'Hello'; 254 } 255 256 @Component 257 struct Child { 258 @Link msg: string; 259 @Link info: Info; 260 261 build() { 262 Text(this.msg + this.info.info) 263 } 264 } 265 266 @Entry 267 @Component 268 struct LinkExample { 269 @State message: string = 'Hello'; 270 @State info: Info = new Info(); 271 272 build() { 273 Column() { 274 // Correct format. 275 Child({msg: this.message, info: this.info}) 276 } 277 } 278 } 279 ``` 280 2815. \@Link cannot decorate variables of the function type. Otherwise, the framework throws a runtime error. 282 283 284## Usage Scenarios 285 286 287### Example for @Link with Simple and Class Types 288 289In 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. 290 291 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. 292 293 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. 294 295```ts 296class GreenButtonState { 297 width: number = 0; 298 299 constructor(width: number) { 300 this.width = width; 301 } 302} 303 304@Component 305struct GreenButton { 306 @Link greenButtonState: GreenButtonState; 307 308 build() { 309 Button('Green Button') 310 .width(this.greenButtonState.width) 311 .height(40) 312 .backgroundColor('#64bb5c') 313 .fontColor('#FFFFFF, 90%') 314 .onClick(() => { 315 if (this.greenButtonState.width < 700) { 316 // Update the attribute of the class. The change can be observed and synchronized back to the parent component. 317 this.greenButtonState.width += 60; 318 } else { 319 // Update the class. The change can be observed and synchronized back to the parent component. 320 this.greenButtonState = new GreenButtonState(180); 321 } 322 }) 323 } 324} 325 326@Component 327struct YellowButton { 328 @Link yellowButtonState: number; 329 330 build() { 331 Button('Yellow Button') 332 .width(this.yellowButtonState) 333 .height(40) 334 .backgroundColor('#f7ce00') 335 .fontColor('#FFFFFF, 90%') 336 .onClick(() => { 337 // The change of the decorated variable of a simple type in the child component can be synchronized back to the parent component. 338 this.yellowButtonState += 40.0; 339 }) 340 } 341} 342 343@Entry 344@Component 345struct ShufflingContainer { 346 @State greenButtonState: GreenButtonState = new GreenButtonState(180); 347 @State yellowButtonProp: number = 180; 348 349 build() { 350 Column() { 351 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) { 352 // Simple type @Link in the child component synchronized from @State in the parent component. 353 Button('Parent View: Set yellowButton') 354 .width(312) 355 .height(40) 356 .margin(12) 357 .fontColor('#FFFFFF, 90%') 358 .onClick(() => { 359 this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 40 : 100; 360 }) 361 // Class type @Link in the child component synchronized from @State in the parent component. 362 Button('Parent View: Set GreenButton') 363 .width(312) 364 .height(40) 365 .margin(12) 366 .fontColor('#FFFFFF, 90%') 367 .onClick(() => { 368 this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100; 369 }) 370 // Initialize the class type @Link. 371 GreenButton({ greenButtonState: $greenButtonState }).margin(12) 372 // Initialize the simple type @Link. 373 YellowButton({ yellowButtonState: $yellowButtonProp }).margin(12) 374 } 375 } 376 } 377} 378``` 379 380 381 382### Array Type \@Link 383 384 385```ts 386@Component 387struct Child { 388 @Link items: number[]; 389 390 build() { 391 Column() { 392 Button(`Button1: push`) 393 .margin(12) 394 .width(312) 395 .height(40) 396 .fontColor('#FFFFFF, 90%') 397 .onClick(() => { 398 this.items.push(this.items.length + 1); 399 }) 400 Button(`Button2: replace whole item`) 401 .margin(12) 402 .width(312) 403 .height(40) 404 .fontColor('#FFFFFF, 90%') 405 .onClick(() => { 406 this.items = [100, 200, 300]; 407 }) 408 } 409 } 410} 411 412@Entry 413@Component 414struct Parent { 415 @State arr: number[] = [1, 2, 3]; 416 417 build() { 418 Column() { 419 Child({ items: $arr }) 420 .margin(12) 421 ForEach(this.arr, 422 (item: number) => { 423 Button(`${item}`) 424 .margin(12) 425 .width(312) 426 .height(40) 427 .backgroundColor('#11a2a2a2') 428 .fontColor('#e6000000') 429 }, 430 (item: ForEachInterface) => item.toString() 431 ) 432 } 433 } 434} 435``` 436 437 438 439As 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. 440 441### Decorating Variables of the Map Type 442 443> **NOTE** 444> 445> Since API version 11, \@Link supports the Map type. 446 447In 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. 448 449```ts 450@Component 451struct Child { 452 @Link value: Map<number, string>; 453 454 build() { 455 Column() { 456 ForEach(Array.from(this.value.entries()), (item: [number, string]) => { 457 Text(`${item[0]}`).fontSize(30) 458 Text(`${item[1]}`).fontSize(30) 459 Divider() 460 }) 461 Button('child init map').onClick(() => { 462 this.value = new Map([[0, "a"], [1, "b"], [3, "c"]]); 463 }) 464 Button('child set new one').onClick(() => { 465 this.value.set(4, "d"); 466 }) 467 Button('child clear').onClick(() => { 468 this.value.clear(); 469 }) 470 Button('child replace the first one').onClick(() => { 471 this.value.set(0, "aa"); 472 }) 473 Button('child delete the first one').onClick(() => { 474 this.value.delete(0); 475 }) 476 } 477 } 478} 479 480 481@Entry 482@Component 483struct MapSample { 484 @State message: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); 485 486 build() { 487 Row() { 488 Column() { 489 Child({ value: this.message }) 490 } 491 .width('100%') 492 } 493 .height('100%') 494 } 495} 496``` 497 498### Decorating Variables of the Set Type 499 500> **NOTE** 501> 502> Since API version 11, \@Link supports the Set type. 503 504In 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. 505 506```ts 507@Component 508struct Child { 509 @Link message: Set<number>; 510 511 build() { 512 Column() { 513 ForEach(Array.from(this.message.entries()), (item: [number, number]) => { 514 Text(`${item[0]}`).fontSize(30) 515 Divider() 516 }) 517 Button('init set').onClick(() => { 518 this.message = new Set([0, 1, 2, 3, 4]); 519 }) 520 Button('set new one').onClick(() => { 521 this.message.add(5); 522 }) 523 Button('clear').onClick(() => { 524 this.message.clear(); 525 }) 526 Button('delete the first one').onClick(() => { 527 this.message.delete(0); 528 }) 529 } 530 .width('100%') 531 } 532} 533 534 535@Entry 536@Component 537struct SetSample { 538 @State message: Set<number> = new Set([0, 1, 2, 3, 4]); 539 540 build() { 541 Row() { 542 Column() { 543 Child({ message: this.message }) 544 } 545 .width('100%') 546 } 547 .height('100%') 548 } 549} 550``` 551 552### Using Two-Way Synchronization Mechanism to Change Local Variables 553 554Use [\@Watch](./arkts-watch.md) to change local variables during two-way synchronization. 555 556In the following example, the \@State decorated variable **memberMessage** is changed 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. 557 558```ts 559@Entry 560@Component 561struct Parent { 562 @State sourceNumber: number = 0; 563 564 build() { 565 Column() { 566 Text(`sourceNumber of the parent component: ` + this.sourceNumber) 567 Child({ sourceNumber: this.sourceNumber }) 568 Button('sourceNumber is changed in the parent component') 569 .onClick(() => { 570 this.sourceNumber++; 571 }) 572 } 573 .width('100%') 574 .height('100%') 575 } 576} 577 578@Component 579struct Child { 580 @State memberMessage: string = 'Hello World'; 581 @Link @Watch('onSourceChange') sourceNumber: number; 582 583 onSourceChange() { 584 this.memberMessage = this.sourceNumber.toString(); 585 } 586 587 build() { 588 Column() { 589 Text(this.memberMessage) 590 Text(`sourceNumber of the child component: ` + this.sourceNumber.toString()) 591 Button('memberMessage is changed in the child component') 592 .onClick(() => { 593 this.memberMessage = 'Hello memberMessage'; 594 }) 595 } 596 } 597} 598``` 599 600## Union Type @Link 601 602@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. 603 604```ts 605@Component 606struct Child { 607 @Link name: string | undefined; 608 609 build() { 610 Column() { 611 612 Button('Child change name to Bob') 613 .onClick(() => { 614 this.name = "Bob"; 615 }) 616 617 Button('Child change name to undefined') 618 .onClick(() => { 619 this.name = undefined; 620 }) 621 622 }.width('100%') 623 } 624} 625 626@Entry 627@Component 628struct Index { 629 @State name: string | undefined = "mary"; 630 631 build() { 632 Column() { 633 Text(`The name is ${this.name}`).fontSize(30) 634 635 Child({ name: this.name }) 636 637 Button('Parents change name to Peter') 638 .onClick(() => { 639 this.name = "Peter"; 640 }) 641 642 Button('Parents change name to undefined') 643 .onClick(() => { 644 this.name = undefined; 645 }) 646 } 647 } 648} 649``` 650 651## FAQs 652 653### Incorrect Type of \@Link Decorated State Variable 654 655When 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. 656 657[Incorrect Example] 658 659```ts 660@Observed 661class Info { 662 public age: number = 0; 663 664 constructor(age: number) { 665 this.age = age; 666 } 667} 668 669@Component 670struct LinkChild { 671 @Link testNum: number; 672 673 build() { 674 Text(`LinkChild testNum ${this.testNum}`) 675 } 676} 677 678@Entry 679@Component 680struct Parent { 681 @State info: Info = new Info(1); 682 683 build() { 684 Column() { 685 Text(`Parent testNum ${this.info.age}`) 686 .onClick(() => { 687 this.info.age += 1; 688 }) 689 // The type of the @Link decorated variable must be the same as that of the @State decorated data source. 690 LinkChild({ testNum: this.info.age }) 691 } 692 } 693} 694``` 695 696In 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})**. 697 698[Correct Example] 699 700```ts 701@Observed 702class Info { 703 public age: number = 0; 704 705 constructor(age: number) { 706 this.age = age; 707 } 708} 709 710@Component 711struct LinkChild { 712 @Link testNum: Info; 713 714 build() { 715 Text(`LinkChild testNum ${this.testNum?.age}`) 716 .onClick(() => { 717 this.testNum.age += 1; 718 }) 719 } 720} 721 722@Entry 723@Component 724struct Parent { 725 @State info: Info = new Info(1); 726 727 build() { 728 Column() { 729 Text(`Parent testNum ${this.info.age}`) 730 .onClick(() => { 731 this.info.age += 1; 732 }) 733 // The type of the @Link decorated variable must be the same as that of the @State decorated data source. 734 LinkChild({ testNum: this.info }) 735 } 736 } 737} 738``` 739 740### Using the a.b(this.object) Format Fails to Trigger UI Re-render 741 742In 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 original 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. 743 744[Incorrect Example] 745 746```ts 747class Score { 748 value: number; 749 constructor(value: number) { 750 this.value = value; 751 } 752 753 static changeScore1(score:Score) { 754 score.value += 1; 755 } 756} 757 758@Entry 759@Component 760struct Parent { 761 @State score: Score = new Score(1); 762 763 build() { 764 Column({space:8}) { 765 Text(`The value in Parent is ${this.score.value}.`) 766 .fontSize(30) 767 .fontColor(Color.Red) 768 Child({ score: this.score }) 769 } 770 .width('100%') 771 .height('100%') 772 } 773} 774 775@Component 776struct Child { 777 @Link score: Score; 778 779 changeScore2(score:Score) { 780 score.value += 2; 781 } 782 783 build() { 784 Column({space:8}) { 785 Text(`The value in Child is ${this.score.value}.`) 786 .fontSize(30) 787 Button(`changeScore1`) 788 .onClick(()=>{ 789 // The UI cannot be re-rendered using a static method. 790 Score.changeScore1(this.score); 791 }) 792 Button(`changeScore2`) 793 .onClick(()=>{ 794 // The UI cannot be re-rendered using this. 795 this.changeScore2(this.score); 796 }) 797 } 798 } 799} 800``` 801 802You can add a proxy for **this.score** to re-render the UI by assigning a value to the variable and then calling the variable. 803 804[Correct Example] 805 806```ts 807class Score { 808 value: number; 809 constructor(value: number) { 810 this.value = value; 811 } 812 813 static changeScore1(score:Score) { 814 score.value += 1; 815 } 816} 817 818@Entry 819@Component 820struct Parent { 821 @State score: Score = new Score(1); 822 823 build() { 824 Column({space:8}) { 825 Text(`The value in Parent is ${this.score.value}.`) 826 .fontSize(30) 827 .fontColor(Color.Red) 828 Child({ score: this.score }) 829 } 830 .width('100%') 831 .height('100%') 832 } 833} 834 835@Component 836struct Child { 837 @Link score: Score; 838 839 changeScore2(score:Score) { 840 score.value += 2; 841 } 842 843 build() { 844 Column({space:8}) { 845 Text(`The value in Child is ${this.score.value}.`) 846 .fontSize(30) 847 Button(`changeScore1`) 848 .onClick(()=>{ 849 // Add a proxy by assigning a value. 850 let score1 = this.score; 851 Score.changeScore1(score1); 852 }) 853 Button(`changeScore2`) 854 .onClick(()=>{ 855 // Add a proxy by assigning a value. 856 let score2 = this.score; 857 this.changeScore2(score2); 858 }) 859 } 860 } 861} 862``` 863 864<!--no_check--> 865