1# ArkUI Subsystem Changelog
2
3## cl.arkui.1 Restrictions on Data Type Declarations of State Variables
4
51. The data types of state variables decorated by state decorators must be explicitly declared. They cannot be declared as **any**.
6
7    Example:
8
9    ```ts
10    // xxx.ets
11    @Entry
12    @Component
13    struct DatePickerExample {
14      // Incorrect: @State isLunar: any = false
15      @State isLunar: boolean = false
16
17      build() {
18      		...
19      }
20    }
21    ```
22
232. The data type declaration of the **@State**, **@Provide**, **@Link**, or **@Consume** decorated state variables can consist of only one of the primitive data types or reference data types.
24
25    The **Length**, **ResourceStr**, and **ResourceColor** types are combinations of primitive data types or reference data types. Therefore, they cannot be used by the aforementioned types of state variables.
26    For details about the definitions of **Length**, **ResourceStr**, and **ResourceColor**, see [Types](../../../application-dev/reference/apis-arkui/arkui-ts/ts-types.md).
27
28    Example:
29
30    ```ts
31    // xxx.ets
32    @Entry
33    @Component
34    struct IndexPage {
35      // Incorrect: @State message: string | Resource = 'Hello World'
36      @State message: string = 'Hello World'
37      // Incorrect: @State message: ResourceStr = $r('app.string.hello')
38      @State resourceStr: Resource = $r('app.string.hello')
39
40      build() {
41        Row() {
42          Column() {
43            Text(`${this.message}`)
44              .fontSize(50)
45              .fontWeight(FontWeight.Bold)
46          }
47          .width('100%')
48        }
49        .height('100%')
50      }
51    }
52    ```
53
54    ![hello](../../../application-dev/quick-start/figures/hello.PNG)
55
56**Change Impacts**
57
581. If the data type of a state variable decorated by a state decorator is declared as **any**, a build error message will be displayed.
59    ```ts
60    // ArkTS:WARN Please define an explicit type, not any.
61    @State isLunar: any = false
62    ```
633. If the data type of a **@State**, **@Provide**, **@Link**, and or **@Consume** decorated state variable is Length, **ResourceStr**, or **ResourceColor**,
64    a build error will occur.
65
66    ```ts
67    /* ArkTS:ERROR The state variable type here is 'ResourceStr', it contains both a simple type and an object type,
68      which are not allowed to be defined for state variable of a struct.*/
69    @State message: ResourceStr = $r('app.string.hello')
70    ```
71
72**Key API/Component Changes**
73
74N/A
75
76**Adaptation Guide**
77
781. Explicitly declare the data type for state variables decorated by state decorators.
793.
80    Adapt the **@State**, **@Provide**, **@Link**, and **@Consume** decorated variables based on the following code snippet so that they do not use the **Length(string|number|Resource)**, **ResourceStr(string|Resource)**, and **ResourceColor(string|number|Color|Resource)** types:
81    ```ts
82    // Incorrect:
83    @State message: ResourceStr = $r('app.string.hello')
84    // Corrected:
85    @State resourceStr: Resource = $r('app.string.hello')
86    ```
87
88## cl.arkui.2 Initialization Rules and Restrictions of Custom Components' Member Variables
89
90Comply with the following rules when using constructors to initialize member variables:
91
92| **From the Variable in the Parent Component (Right) to the Variable in the Child Component (Below)**| **regular** | **@State** | **@Link** | **@Prop** | **@Provide** | **@Consume** | **@ObjectLink** |
93| -------------------------- | ----------- | ---------- | --------- | --------- | ------------ | ------------ | --------------- |
94| **regular**                | Supported         | Supported        | Supported       | Supported       | Not supported         | Not supported         | Supported             |
95| **@State**                 | Supported         | Supported        | Supported       | Supported       | Supported          | Supported          | Supported             |
96| **@Link**                  | Not supported        | Supported (1)     | Supported (1)    | Supported (1)    | Supported (1)       | Supported (1)       | Supported (1)          |
97| **@Prop**                  | Supported         | Supported        | Supported       | Supported       | Supported          | Supported          | Supported             |
98| **@Provide**               | Supported         | Supported        | Supported       | Supported       | Supported          | Supported          | Supported             |
99| **@Consume**               | Not supported        | Not supported       | Not supported      | Not supported      | Not supported         | Not supported         | Not supported            |
100| **@ObjectLink**            | Not supported        | Not supported       | Not supported      | Not supported      | Not supported         | Not supported         | Not supported            |
101
102| **From the Variable in the Parent Component (Right) to the Variable in the Child Component (Below)**| **@StorageLink** | **@StorageProp** | **@LocalStorageLink** | **@LocalStorageProp** |
103| -------------------------- | ---------------- | ---------------- | --------------------- | --------------------- |
104| **regular**                | Supported              | Not supported             | Not supported                  | Not supported                  |
105| **@State**                 | Supported              | Supported              | Supported                   | Supported                   |
106| **@Link**                  | Supported (1)           | Supported (1)           | Supported (1)                | Supported (1)                |
107| **@Prop**                  | Supported              | Supported              | Supported                   | Supported                   |
108| **@Provide**               | Supported              | Supported              | Supported                   | Supported                   |
109| **@Consume**               | Not supported             | Not supported             | Not supported                  | Not supported                  |
110| **@ObjectLink**            | Not supported             | Not supported             | Not supported                  | Not supported                  |
111
112> **NOTE**
113>
114> **Supported (1)**: The dollar sign ($) must be used, for example, **this.$varA**.
115>
116> **regular**: refers to a regular variable that is not decorated by any decorator.
117
118**@StorageLink**, **@StorageProp**, **@LocalStorageLink**, and **@LocalStorageProp** variables cannot be initialized from the parent component.
119
120**Change Impacts**
121
1221. **@LocalStorageLink** and **@LocalStorageProp** variables cannot be initialized from the parent component. Otherwise, a build error message will be displayed.
123    ```ts
124    @Entry
125    @Component
126    struct LocalStorageComponent {
127        build() {
128            Column() {
129                Child({
130                  /* ArkTS:WARN Property 'simpleVarName' in the custom component 'Child' cannot
131                    initialize here (forbidden to specify). */
132                  simpleVarName: 1,
133                  /* ArkTS:WARN Property 'objectName' in the custom component 'Child' cannot
134                    initialize here (forbidden to specify). */
135                  objectName: new ClassA("x")
136                })
137            }
138        }
139    }
140    @Component
141    struct Child {
142        @LocalStorageLink("storageSimpleProp") simpleVarName: number = 0;
143        @LocalStorageProp("storageObjectProp") objectName: ClassA = new ClassA("x");
144        build() {}
145    }
146    ```
1472. The **@ObjectLink** decorated variable cannot be directly initialized from a decorated variable in the parent component. The source of the parent component must be an array item or object attribute decorated by **@State**, **@Link**, **@Provide**, **@Consume**, or **@ObjectLink**.
148    ```ts
149    let NextID : number = 0;
150
151    @Observed class ClassA {
152      public id : number;
153      public c: number;
154      constructor(c: number) {
155        this.id = NextID++;
156        this.c = c;
157      }
158    }
159
160    @Component
161    struct Child {
162      @ObjectLink varA : ClassA;
163      build() {
164        Row() {
165          Text('ViewA-' + this.varA.id)
166        }
167      }
168    }
169
170    @Component
171    struct Parent {
172      @Link linkValue: ClassA
173      build() {
174        Column() {
175          /* ArkTS:ERROR The @Link property 'linkValue' cannot be assigned to
176            the @ObjectLink property 'varA'.*/
177          Child({ varA: this.linkValue })
178        }
179      }
180    }
181    ```
182
183**Key API/Component Changes**
184
185N/A
186
187**Adaptation Guide**
1881. When building a child component, do not assign values to the variables decorated by **@LocalStorageLink** and **@LocalStorageProp** in the child component.
189
190    To change these variables from the parent component, use the API provided by the **LocalStorage** (such as the **set** API) to assign values to them.
191
1922. For details about how to use **@ObjectLink**, see [\@Observed and \@ObjectLink Decorators: Observing Property Changes in Nested Class Objects](../../../application-dev/quick-start/arkts-observed-and-objectlink.md).
193
194## cl.arkui.3 Change of the onScrollBegin Event of the \<List> and \<Scroll> Components
195
196The **onScrollBegin** event of the **\<List>** and **\<Scroll>** components is renamed **onScrollFrameBegin**. In the **onScrollBegin** event, the amount to scroll by is indicated by the **dx** and **dy** parameters. In the **onScrollFrameBegin** event, it is indicated by the **offset** parameter. The **onScrollFrameBegin** event adds the **ScrollState** parameter to indicate whether the component is in the finger dragging or inertial scrolling state.
197
198**Change Impacts**
199
200The **onScrollBegin** event is deprecated and must be replaced with the **onScrollFrameBegin** event.
201
202**Key API/Component Changes**
203
204| Old Event                                   | New Event                                   |
205| ---------------------------------------- | ---------------------------------------- |
206| onScrollBegin(event: (dx: number, dy: number) => { dxRemain: number, dyRemain: number }) | onScrollFrameBegin(event: (offset: number, state: ScrollState) => { offsetRemain: number }) |
207
208For details about the **onScrollFrameBegin** event, see the following:
209- [Scroll Events](../../../application-dev/reference/apis-arkui/arkui-ts/ts-container-scroll.md#events)
210- [List Events](../../../application-dev/reference/apis-arkui/arkui-ts/ts-container-list.md#events)
211
212**Adaptation Guide**
213
214Switch the event from **onScrollBegin** to **onScrollFrameBegin**, and use the **offset** parameter in **onScrollFrameBegin**, rather than the **dx** and **dy** parameters in **onScrollBegin**, to indicate the amount to scroll by.
215
216Example of using the **onScrollBegin** event:
217```ts
218@Entry
219@Component
220struct NestedScroll {
221  @State listPosition: number = 0; // 0 indicates scrolling to the top of the list, 1 indicates scrolling to the middle of the list, and 2 indicates scrolling to the bottom of the list.
222  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
223  private scrollerForScroll: Scroller = new Scroller()
224  private scrollerForList: Scroller = new Scroller()
225
226  build() {
227    Flex() {
228      Scroll(this.scrollerForScroll) {
229        Column() {
230          Text("Scroll Area")
231            .width("100%").height("40%").backgroundColor(0X330000FF)
232            .fontSize(16).textAlign(TextAlign.Center)
233            .onClick(() => {
234              this.scrollerForList.scrollToIndex(5)
235            })
236
237          List({ space: 20, scroller: this.scrollerForList }) {
238            ForEach(this.arr, (item) => {
239              ListItem() {
240                Text("ListItem" + item)
241                  .width("100%").height("100%").borderRadius(15)
242                  .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)
243              }.width("100%").height(100)
244            }, item => item)
245          }
246          .width("100%")
247          .height("50%")
248          .edgeEffect(EdgeEffect.None)
249          .onReachStart(() => {
250            this.listPosition = 0
251          })
252          .onReachEnd(() => {
253            this.listPosition = 2
254          })
255          .onScrollBegin((dx: number, dy: number) => {
256            if ((this.listPosition == 0 && dy >= 0) || (this.listPosition == 2 && dy <= 0)) {
257              this.scrollerForScroll.scrollBy(0, -dy)
258              return { dxRemain: dx, dyRemain: 0 }
259            }
260            this.listPosition = 1
261            return { dxRemain: dx, dyRemain: dy };
262          })
263
264          Text("Scroll Area")
265            .width("100%").height("40%").backgroundColor(0X330000FF)
266            .fontSize(16).textAlign(TextAlign.Center)
267        }
268      }
269      .width("100%").height("100%")
270    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
271  }
272}
273```
274Example of using the **onScrollFrameBegin** event:
275```ts
276@Entry
277@Component
278struct NestedScroll {
279  @State listPosition: number = 0; // 0 indicates scrolling to the top of the list, 1 indicates scrolling to the middle of the list, and 2 indicates scrolling to the bottom of the list.
280  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
281  private scrollerForScroll: Scroller = new Scroller()
282  private scrollerForList: Scroller = new Scroller()
283
284  build() {
285    Flex() {
286      Scroll(this.scrollerForScroll) {
287        Column() {
288          Text("Scroll Area")
289            .width("100%").height("40%").backgroundColor(0X330000FF)
290            .fontSize(16).textAlign(TextAlign.Center)
291            .onClick(() => {
292              this.scrollerForList.scrollToIndex(5)
293            })
294
295          List({ space: 20, scroller: this.scrollerForList }) {
296            ForEach(this.arr, (item) => {
297              ListItem() {
298                Text("ListItem" + item)
299                  .width("100%").height("100%").borderRadius(15)
300                  .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)
301              }.width("100%").height(100)
302            }, item => item)
303          }
304          .width("100%")
305          .height("50%")
306          .edgeEffect(EdgeEffect.None)
307          .onReachStart(() => {
308            this.listPosition = 0
309          })
310          .onReachEnd(() => {
311            this.listPosition = 2
312          })
313          .onScrollFrameBegin((offset: number, state: ScrollState) => {
314            if ((this.listPosition == 0 && offset >= 0) || (this.listPosition == 2 && offset <= 0)) {
315              this.scrollerForScroll.scrollBy(0, -offset)
316              return { offsetRemain: 0 }
317            }
318            this.listPosition = 1
319            return { offsetRemain: offset };
320          })
321
322          Text("Scroll Area")
323            .width("100%").height("40%").backgroundColor(0X330000FF)
324            .fontSize(16).textAlign(TextAlign.Center)
325        }
326      }
327      .width("100%").height("100%")
328    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
329  }
330}
331```
332