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