• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![en-us_image_0000001502092556](figures/en-us_image_0000001502092556.png)
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![Video-link-UsageScenario-one](figures/Video-link-UsageScenario-one.gif)
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![Video-link-UsageScenario-two](figures/Video-link-UsageScenario-two.gif)
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