• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Custom Component Lifecycle
2
3The lifecycle callbacks of a custom component are used to notify users of the lifecycle of the component. These callbacks are private and are invoked by the development framework at a specified time at runtime. They cannot be manually invoked from applications. Do not reuse the same custom component node across multiple windows, as otherwise its lifecycle may become disrupted.
4
5>**NOTE**
6>
7>- The initial APIs of this module are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version.
8>- Promise and asynchronous callback functions can be used in lifecycle functions, for example, network resource getters and timer setters.
9
10
11## aboutToAppear
12
13aboutToAppear?(): void
14
15Invoked after a new instance of the custom component is created and before its **build()** function is executed. You can change state variables in **aboutToAppear**. The change will take effect when you execute the **build()** function next time. The **aboutToAppear** lifecycle callback of a custom component with a custom layout is invoked during the layout process.
16
17> **NOTE**
18>
19> * In this callback function, it is recommended that you only perform initialization logic for the current node component. Avoid high-time-consuming operations that may block the main thread. For high-time-consuming operations, consider caching or asynchronous solutions. For best practices, see [Optimizing Performance of UI Components: Avoiding Time-Consuming Operations During the Lifecycle of Custom Components](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-ui-component-performance-optimization#section18755173594714).
20> * In scenarios where components need to be frequently created and destroyed, this callback will be called frequently. For best practices, see [Optimizing Time-Consuming Operations in the Main Thread: Component Lifecycle Callback](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-time-optimization-of-the-main-thread#section418843713435).
21
22**Widget capability**: This API can be used in ArkTS widgets since API version 9.
23
24**Atomic service API**: This API can be used in atomic services since API version 11.
25
26**System capability**: SystemCapability.ArkUI.ArkUI.Full
27
28## onDidBuild<sup>12+</sup>
29
30onDidBuild?(): void
31
32Invoked after the **build()** function of the custom component is executed. You can use this callback for actions that do not directly affect the UI, such as tracking data reporting. Do not change state variables or use functions (such as **animateTo**) in **onDidBuild**. Otherwise, unstable UI performance may result.
33
34**Atomic service API**: This API can be used in atomic services since API version 12.
35
36**System capability**: SystemCapability.ArkUI.ArkUI.Full
37
38## aboutToDisappear
39
40aboutToDisappear?(): void
41
42Invoked when this component is about to disappear. Do not change state variables in the **aboutToDisappear** function as doing this can cause unexpected errors. For example, the modification of the **@Link** decorated variable may cause unstable application running.
43
44> **NOTE**
45>
46> In scenarios where components need to be frequently created and destroyed, this callback will be called frequently. For best practices, see [Optimizing Time-Consuming Operations in the Main Thread: Component Lifecycle Callback](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-time-optimization-of-the-main-thread#section418843713435).
47
48**Widget capability**: This API can be used in ArkTS widgets since API version 9.
49
50**Atomic service API**: This API can be used in atomic services since API version 11.
51
52**System capability**: SystemCapability.ArkUI.ArkUI.Full
53
54## onPageShow
55
56onPageShow?(): void
57
58Triggered each time a router-managed page (only custom components decorated with [\@Entry](../../../../application-dev/ui/state-management/arkts-create-custom-components.md#entry)) is displayed, including scenarios such as route navigation and the application returning to the foreground.
59
60**Atomic service API**: This API can be used in atomic services since API version 11.
61
62**System capability**: SystemCapability.ArkUI.ArkUI.Full
63
64## onPageHide
65
66onPageHide?(): void
67
68Triggered each time a router-managed page (only custom components decorated with [\@Entry](../../../../application-dev/ui/state-management/arkts-create-custom-components.md#entry)) is hidden, including scenarios such as route navigation and the application moving to background.
69
70> **NOTE**
71>
72> To ensure smooth UI responsiveness, avoid executing time-consuming operations within the callback function that may block the main thread. For resource-intensive tasks such as camera resource deallocation, consider implementing asynchronous solutions. For best practices, see [Reducing Application Latency: Postponing Resource Release](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-application-latency-optimization-cases#section8783201923819).
73
74**Atomic service API**: This API can be used in atomic services since API version 11.
75
76**System capability**: SystemCapability.ArkUI.ArkUI.Full
77
78## onBackPress
79
80onBackPress?(): void | boolean
81
82Triggered when the user clicks the back button (only effective for router-managed pages). The value **true** means that the page executes its own return logic, and **false** (default) means that the default return logic is used.
83
84**Atomic service API**: This API can be used in atomic services since API version 11.
85
86**System capability**: SystemCapability.ArkUI.ArkUI.Full
87
88**Return value**
89
90| Type               | Description       |
91| ------------------- | --------- |
92| void \| boolean | Action of the back button. The value **true** means that the page executes its own return logic, and **false** (default) means that the default return logic is used.|
93
94```ts
95// xxx.ets
96@Entry
97@Component
98struct IndexComponent {
99  @State textColor: Color = Color.Black;
100
101  onPageShow() {
102    this.textColor = Color.Blue;
103    console.info('IndexComponent onPageShow');
104  }
105
106  onPageHide() {
107    this.textColor = Color.Transparent;
108    console.info('IndexComponent onPageHide');
109  }
110
111  onBackPress() {
112    this.textColor = Color.Red;
113    console.info('IndexComponent onBackPress');
114  }
115
116  build() {
117    Column() {
118      Text('Hello World')
119        .fontColor(this.textColor)
120        .fontSize(30)
121        .margin(30)
122    }.width('100%')
123  }
124}
125```
126![en-us_image_lifecycle](figures/en-us_image_lifecycle.gif)
127
128## onNewParam<sup>19+</sup>
129
130onNewParam?(param: ESObject): void
131
132Triggered when a page previously existing in the navigation stack is brought to the top through navigation in [single-instance](../js-apis-router.md#routermode9) mode. It is only effective for custom components decorated with [\@Entry](../../../../application-dev/ui/state-management/arkts-create-custom-components.md#entry) that serve as [router-managed](../js-apis-router.md) pages.
133
134**Atomic service API**: This API can be used in atomic services since API version 19.
135
136**System capability**: SystemCapability.ArkUI.ArkUI.Full
137
138**Parameters**
139
140| Name| Type    |              Description        |
141|-------|----------|---------------------------|
142| param | ESObject | Data passed to the target page during redirection.|
143
144```ts
145// pages/Index.ets
146import { router } from '@kit.ArkUI';
147
148export class routerParam {
149  msg: string = '__NA__';
150
151  constructor(msg: string) {
152    this.msg = msg;
153  }
154}
155
156@Entry
157@Component
158struct Index {
159  aboutToAppear(): void {
160    console.log('onNewParam', 'Index aboutToAppear');
161  }
162
163  onNewParam(param: ESObject) {
164    console.log('onNewParam', 'Index onNewParam, param: ' + JSON.stringify(param));
165  }
166
167  build() {
168    Column() {
169      Button('push pageOne Standard')
170        .margin(10)
171        .onClick(() => {
172          this.getUIContext().getRouter().pushUrl({
173            url: 'pages/PageOne',
174            params: new routerParam('push pageOne Standard')
175          }, router.RouterMode.Standard);
176        })
177      Button('push pageOne Single')
178        .margin(10)
179        .onClick(() => {
180          this.getUIContext().getRouter().pushUrl({
181            url: 'pages/PageOne',
182            params: new routerParam('push pageOne Single')
183          }, router.RouterMode.Single)
184        })
185    }
186    .width('100%')
187    .height('100%')
188  }
189}
190```
191<!--code_no_check-->
192```ts
193// pages/PageOne.ets
194import { router } from '@kit.ArkUI';
195import { routerParam } from './Index';
196
197@Entry
198@Component
199struct PageOne {
200  aboutToAppear(): void {
201    console.log('onNewParam', 'PageOne aboutToAppear');
202  }
203
204  onNewParam(param: ESObject) {
205    console.log('onNewParam', 'PageOne onNewParam, param: ' + JSON.stringify(param));
206  }
207
208  build() {
209    Column() {
210      Button('push Index Standard')
211        .margin(10)
212        .onClick(() => {
213          this.getUIContext().getRouter().pushUrl({
214            url: 'pages/Index',
215            params: new routerParam('push Index Standard')
216          }, router.RouterMode.Standard);
217        })
218      Button('push Index Single')
219        .margin(10)
220        .onClick(() => {
221          this.getUIContext().getRouter().pushUrl({
222            url: 'pages/Index',
223            params: new routerParam('push Index Single')
224          }, router.RouterMode.Single)
225        })
226    }
227    .width('100%')
228    .height('100%')
229  }
230}
231```
232
233## aboutToReuse<sup>10+</sup>
234
235aboutToReuse?(params: Record\<string, Object | undefined | null>): void
236
237Invoked when a reusable custom component is re-added to the node tree from the reuse cache to receive construction parameters of the component.
238
239> **NOTE**
240>
241> * Avoid repeatedly updating state variables that are automatically updated, such as @Link, @ObjectLink, and @Prop decorated variables, within **aboutToReuse**. For best practices, see [Component Reuse: Avoiding Repeated Assignment of Automatically Updated State Variables in aboutToReuse()](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-component-reuse#section7441712174414).
242> * In scrolling scenarios where component reuse is implemented, this callback is typically required to update the component's state variables. As such, avoid performing time-consuming operations within this callback to prevent frame drops and UI stuttering during scrolling animations. For best practices, see [Optimizing Time-Consuming Operations in the Main Thread: Component Reuse Callback](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-time-optimization-of-the-main-thread#section20815336174316).
243
244**Atomic service API**: This API can be used in atomic services since API version 11.
245
246**System capability**: SystemCapability.ArkUI.ArkUI.Full
247
248**Parameters**
249
250| Name | Type                                     | Description               |
251|--------|-------------------------------------------|---------------------|
252| params | Record\<string, Object \| undefined \| null> | Construction parameters of the custom component.|
253
254```ts
255// xxx.ets
256export class Message {
257  value: string | undefined;
258
259  constructor(value: string) {
260    this.value = value
261  }
262}
263
264@Entry
265@Component
266struct Index {
267  @State switch: boolean = true
268
269  build() {
270    Column() {
271      Button('Hello World')
272        .fontSize(50)
273        .fontWeight(FontWeight.Bold)
274        .onClick(() => {
275          this.switch = !this.switch
276        })
277      if (this.switch) {
278        Child({ message: new Message('Child') })
279      }
280    }
281    .height("100%")
282    .width('100%')
283  }
284}
285
286@Reusable
287@Component
288struct Child {
289  @State message: Message = new Message('AboutToReuse');
290
291  aboutToReuse(params: Record<string, ESObject>) {
292    console.info("Recycle Child")
293    this.message = params.message as Message
294  }
295
296  build() {
297    Column() {
298      Text(this.message.value)
299        .fontSize(20)
300    }
301    .borderWidth(2)
302    .height(100)
303  }
304}
305```
306
307## aboutToReuse<sup>18+</sup>
308
309aboutToReuse?(): void
310
311Invoked when a reusable custom component managed by state management V2 is taken from the reuse pool and reinserted into the node tree.
312
313For details, see [\@ReusableV2](../../../ui/state-management/arkts-new-reusableV2.md).
314
315**Atomic service API**: This API can be used in atomic services since API version 18.
316
317**System capability**: SystemCapability.ArkUI.ArkUI.Full
318
319```ts
320@Entry
321@ComponentV2
322struct Index {
323  @Local condition: boolean = true;
324  build() {
325    Column() {
326      Button('Recycle/Reuse').onClick(()=>{this.condition=!this.condition;}) // Click to switch the recycle/reuse state.
327      if (this.condition) {
328        ReusableV2Component()
329      }
330    }
331  }
332}
333@ReusableV2
334@ComponentV2
335struct ReusableV2Component {
336  @Local message: string = 'Hello World';
337  aboutToReuse() {
338    console.log('ReusableV2Component aboutToReuse'); // Called when a component is reused.
339  }
340  build() {
341    Column() {
342      Text(this.message)
343    }
344  }
345}
346```
347
348
349## aboutToRecycle<sup>10+</sup>
350
351aboutToRecycle?(): void
352
353Invoked when this reusable component is about to be added from the component tree to the reuse cache.
354
355**Atomic service API**: This API can be used in atomic services since API version 11.
356
357**System capability**: SystemCapability.ArkUI.ArkUI.Full
358
359```ts
360// xxx.ets
361export class Message {
362  value: string | undefined;
363
364  constructor(value: string) {
365    this.value = value;
366  }
367}
368
369@Entry
370@Component
371struct Index {
372  @State switch: boolean = true;
373
374  build() {
375    Column() {
376      Button('Hello World')
377        .fontSize(50)
378        .fontWeight(FontWeight.Bold)
379        .onClick(() => {
380          this.switch = !this.switch;
381        })
382      if (this.switch) {
383        Child({ message: new Message('Child') })
384      }
385    }
386    .height("100%")
387    .width('100%')
388  }
389}
390
391@Reusable
392@Component
393struct Child {
394  @State message: Message = new Message('AboutToReuse');
395
396  aboutToReuse(params: Record<string, ESObject>) {
397    console.info("Reuse Child");
398    this.message = params.message as Message;
399  }
400
401  aboutToRecycle() {
402    // This is where you can release memory-intensive content or other non-essential resource references to avoid continuous memory usage that could lead to memory leaks.
403    console.info("The child enters the recycle pool.");
404  }
405
406  build() {
407    Column() {
408      Text(this.message.value)
409        .fontSize(20)
410    }
411    .borderWidth(2)
412    .height(100)
413  }
414}
415```
416
417## onWillApplyTheme<sup>12+</sup>
418
419onWillApplyTheme?(theme: Theme): void
420
421Invoked before the **build()** function of a new instance of the custom component is executed, to obtain the **Theme** object of the component context. You can change state variables in **onWillApplyTheme**. The change will take effect when you execute the **build()** function next time.
422
423> **NOTE**
424>
425> Since API version 18, this API is supported in the components of V2.
426
427**Atomic service API**: This API can be used in atomic services since API version 12.
428
429**System capability**: SystemCapability.ArkUI.ArkUI.Full
430
431**Parameters**
432
433| Name   | Type                                      | Description        |
434|--------|------------------------------------------|------------|
435| theme | [Theme](../js-apis-arkui-theme.md#theme) | Current theme object of the custom component.|
436
437V1:
438
439```ts
440// xxx.ets
441import { CustomTheme, CustomColors, Theme, ThemeControl } from '@kit.ArkUI';
442
443class BlueColors implements CustomColors {
444  fontPrimary = Color.White;
445  backgroundPrimary = Color.Blue;
446  brand = Color.Blue; // Brand color
447}
448
449class PageCustomTheme implements CustomTheme {
450  colors?: CustomColors;
451
452  constructor(colors: CustomColors) {
453    this.colors = colors;
454  }
455}
456const BlueColorsTheme = new PageCustomTheme(new BlueColors());
457// setDefaultTheme should be called on the application entry page or in an ability.
458ThemeControl.setDefaultTheme(BlueColorsTheme);
459
460@Entry
461@Component
462struct IndexComponent {
463  @State textColor: ResourceColor = $r('sys.color.font_primary');
464  @State columBgColor: ResourceColor = $r('sys.color.background_primary');
465
466  // Obtain the Theme object of the current component context. Set textColor and columBgColor in onWillApplyTheme to the color (BlueColorsTheme) of the Theme object in use.
467  onWillApplyTheme(theme: Theme) {
468    this.textColor = theme.colors.fontPrimary;
469    this.columBgColor = theme.colors.backgroundPrimary;
470    console.info('IndexComponent onWillApplyTheme');
471  }
472
473  build() {
474    Column() {
475      // Initial color style of the component
476      Column() {
477        Text('Hello World')
478          .fontColor($r('sys.color.font_primary'))
479          .fontSize(30)
480      }
481      .width('100%')
482      .height('25%')
483      .borderRadius('10vp')
484      .backgroundColor($r('sys.color.background_primary'))
485
486      // The color style configured in onWillApplyTheme is applied.
487      Column() {
488        Text('onWillApplyTheme')
489          .fontColor(this.textColor)
490          .fontSize(30)
491        Text('Hello World')
492          .fontColor(this.textColor)
493          .fontSize(30)
494      }
495      .width('100%')
496      .height('25%')
497      .borderRadius('10vp')
498      .backgroundColor(this.columBgColor)
499    }
500    .padding('16vp')
501    .backgroundColor('#dcdcdc')
502    .width('100%')
503    .height('100%')
504  }
505}
506```
507![onWillApplyThemePage](figures/onWillApplyTheme.png)
508
509V2:
510
511```ts
512import { CustomTheme, CustomColors, Theme, ThemeControl } from '@kit.ArkUI';
513
514class BlueColors implements CustomColors {
515  fontPrimary = Color.White;
516  backgroundPrimary = Color.Blue;
517  brand = Color.Blue; // Brand color
518}
519
520class PageCustomTheme implements CustomTheme {
521  colors?: CustomColors;
522
523  constructor(colors: CustomColors) {
524    this.colors = colors;
525  }
526}
527
528const BlueColorsTheme = new PageCustomTheme(new BlueColors());
529// setDefaultTheme should be called on the application entry page or in an ability.
530ThemeControl.setDefaultTheme(BlueColorsTheme);
531
532@Entry
533@ComponentV2
534struct IndexComponent {
535  @Local textColor: ResourceColor = $r('sys.color.font_primary');
536  @Local columBgColor: ResourceColor = $r('sys.color.background_primary');
537
538  // Obtain the Theme object of the current component context. Set textColor and columBgColor in onWillApplyTheme to the color (BlueColorsTheme) of the Theme object in use.
539  onWillApplyTheme(theme: Theme) {
540    this.textColor = theme.colors.fontPrimary;
541    this.columBgColor = theme.colors.backgroundPrimary;
542    console.info('IndexComponent onWillApplyTheme');
543  }
544
545  build() {
546    Column() {
547      // Initial color style of the component
548      Column() {
549        Text('Hello World')
550          .fontColor($r('sys.color.font_primary'))
551          .fontSize(30)
552      }
553      .width('100%')
554      .height('25%')
555      .borderRadius('10vp')
556      .backgroundColor($r('sys.color.background_primary'))
557
558      // The color style configured in onWillApplyTheme is applied.
559      Column() {
560        Text('onWillApplyTheme')
561          .fontColor(this.textColor)
562          .fontSize(30)
563        Text('Hello World')
564          .fontColor(this.textColor)
565          .fontSize(30)
566      }
567      .width('100%')
568      .height('25%')
569      .borderRadius('10vp')
570      .backgroundColor(this.columBgColor)
571    }
572    .padding('16vp')
573    .backgroundColor('#dcdcdc')
574    .width('100%')
575    .height('100%')
576  }
577}
578```
579
580![onWillApplyTheme_V2](figures/onWillApplyTheme_V2.png)
581