1# ArkUI Subsystem Changelog
2
3## cl.arkui.1 Verification Against Undefined Keys for Decorators
4
5**Access Level**
6
7Public
8
9**Reason for Change**
10
11The **key** value should be verified for all decorators to comply with TypeScript syntax rules.
12
13The following decorators are involved:
14
15@LocalStorageLink, @LocalStorageProp, @StorageProp, @StorageLink, @Provide, @Consume, @Watch
16
17**Change Impact**
18
19If the **key** value of any of the aforementioned decorators is not defined, a compilation error is reported.
20
21This change is a non-compatible change.
22
23**Start API Level**
24
25@LocalStorageLink: API version 9
26
27@LocalStorageProp: API version 9
28
29@StorageProp: API version 7
30
31@StorageLink: API version 7
32
33@Provide: API version 7
34
35@Consume: API version 7
36
37@Watch: API version 7
38
39
40
41**Change Since**
42
43OpenHarmony SDK 5.0.0.13
44
45Example:
46
47```
48@Entry
49@Component
50struct ComA {
51  // ERROR: Cannot find name 'aaa'.
52  @StorageProp(aaa) storageProp: string = 'storageProp';
53  // ERROR: Cannot find name 'aaa'.
54  @StorageLink(aaa) storageLink: string = 'storageLink';
55  // ERROR: Cannot find name 'aaa'.
56  @LocalStorageLink(aaa) localStorageLink: string = 'localStorageLink';
57  // ERROR: Cannot find name 'aaa'.
58  @LocalStorageProp(aaa) localStorageProp: string = 'localStorageProp';
59  // ERROR: Cannot find name 'aaa'.
60  @Provide(aaa) provide: string = 'provide';
61  // ERROR: Cannot find name 'aaa'.
62  @Consume(aaa) consume: number;
63  // ERROR: Cannot find name 'aaa'.
64  @State @Watch(aaa) watch: number = 0;
65
66  build() {
67  }
68}
69
70```
71
72**Adaptation Guide**
73
74 Make sure the **key** value for the following decorators is defined: @LocalStorageLink, @LocalStorageProp, @StorageProp, @StorageLink, @Provide, @Consume, and @Watch.
75
76```
77// test.ts
78export let oneKey = 'string';
79```
80
81
82
83```
84
85// index.ets
86import { oneKey } from './test';
87@Entry
88@Component
89struct ComA {
90  @StorageProp(oneKey) storageProp: string = 'storageProp';
91  @StorageLink(oneKey) storageLink: string = 'storageLink';
92  @LocalStorageLink(oneKey) localStorageLink: string = 'localStorageLink';
93  @LocalStorageProp(oneKey) localStorageProp: string = 'localStorageProp';
94  @Provide(oneKey) provide: string = 'provide';
95  @Consume(oneKey) consume: number;
96
97  build() {
98  }
99}
100```
101
102
103
104
105## cl.arkui.2 Addition of undefined and null Support for AppStorage, LocalStorage, and PersistentStorage
106
107**Access Level**
108
109Public
110
111**Change Impact**
112
113The AppStorage, LocalStorage, and PersistentStorage APIs now accept **null** and **undefined** as input parameters. The @StorageLink, @StorageProp, @LocalStorageLink, and @LocalStorageProp decorators now support **null** and **undefined** types.
114
115Take @StorageLink as an example. If an AppStorage API uses **null** or **undefined** as the initial or target value, then: In the semantics before change, calling the API reports a warning and does not take effect. In the semantics after change, **null** or **undefined** is saved as the initial or target value in AppStorage. This change causes the original application code to crash in the following scenario:
116
117Before change:
118
119```ts
120class PropA {
121  num: number = 100;
122}
123
124AppStorage.setOrCreate("PropA", null);
125AppStorage.has("PropA");// Because null and undefined are not supported, false is returned.
126
127@Entry
128@Component
129struct TestPage {
130  @StorageLink('PropA') propA: PropA = new PropA();
131
132  build() {
133    Column() {
134      Text(this.propA.num.toString()) // propA is locally initialized to 100.
135    }
136  }
137}
138```
139
140After change:
141
142```ts
143class PropA {
144  num: number = 100;
145}
146
147AppStorage.setOrCreate("PropA", null);
148AppStorage.has("PropA");// Because null and undefined are supported, true is returned.
149
150@Entry
151@Component
152struct TestPage {
153  @StorageLink('PropA') propA: PropA = new PropA();
154
155  build() {
156    Column() {
157      Text(this.propA.num.toString()) // propA is initialized with the value null in AppStorage. As a result, JsCrash is triggered during invoking.
158    }
159  }
160}
161```
162
163**Key API/Component Changes**
164
165AppStorage: **set**, **setOrCreate**, **setAndLink**, **setAndProp**
166
167LocalStorage: **set**, **setOrCreate**, **setAndLink**, **setAndProp**
168
169PersistentStorage: **persistProp**
170
171
172**Start API Level**
173
174This change takes effect since API version 12.
175
176AppStorage
177
178**set**: API version 10
179
180**setOrCreate**: API version 10
181
182**setAndLink**: API version 10
183
184**setAndProp**: API version 10
185
186LocalStorage
187
188**set**: API version 9
189
190**setOrCreate**: API version 9
191
192**setAndLink**: API version 9
193
194**setAndProp**: API version 9
195
196PersistentStorage
197
198**persistProp**: API version 10
199
200**Change Since**
201
202OpenHarmony SDK 5.0.0.13
203
204**Adaptation Guide**
205
2061. Do not use **null** or **undefined** to initialize variables. Use meaningful values instead.
207
2082. Changing a value to **null** or **undefined** will trigger UI re-render.
209
2103. Add a null check to the invoking position.
211
212```ts
213class PropA {
214  num: number = 100;
215}
216
217AppStorage.setOrCreate("PropA", null);
218AppStorage.has("PropA"); // Because null and undefined are supported, true is returned.
219
220@Entry
221@Component
222struct TestPage {
223  @StorageLink('PropA') propA: PropA | null | undefined = new PropA();
224
225  build() {
226    Column() {
227      Text(this.propA?.num.toString())// Check whether the value is null to prevent crashes caused by null and undefined during invoking.
228        .fontSize(20)
229      Button("Set propA to null")
230        .margin(10)
231        .onClick(() => {
232          this.propA = null;
233        })
234      Button("Set propA to undefined")
235        .margin(10)
236        .onClick(() => {
237          this.propA = undefined;
238        })
239      Button("Assign new PropA")
240        .margin(10)
241        .onClick(() => {
242          this.propA = new PropA();
243        })
244    }
245  }
246}
247```
248