• 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**.|
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`)
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![Video-link-UsageScenario-one](figures/Video-link-UsageScenario-one.gif)
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![Video-link-UsageScenario-two](figures/Video-link-UsageScenario-two.gif)
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