DEV Community

Cover image for HarmonyOS Development: Why Key Value Generation Function Is Important in ForEach
程序员一鸣
程序员一鸣

Posted on

HarmonyOS Development: Why Key Value Generation Function Is Important in ForEach

Foreword 

this article is based on Api12 

when using List components, such as List, Grid, waterFlow, etc, loop rendering will be used to ForEach or lazyForEach, of course, also has a separate use scenario, as follows, a very simple list component use, this use, in many official cases also appeared many times, I believe in the actual development of more or less will also exist.

 

List({ space: 20, initialIndex: 0 }) {
ForEach (["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"], (item: string)=>{
ListItem() {
Text(item)
.width('100%')
.height(50)
.fontSize(16)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
}
}, (item: string) => item)
}.padding({ left: 20, right: 20 })
Enter fullscreen mode Exit fullscreen mode

The above code does not seem to have any problems, and UI can also be displayed normally, as shown in the following figure: 

Image description

as if it was all right,, the above code will have some problems, that is, rendering is not expected, we continue to verify the problem and add a button to add data. Of course, we need to extract the data source to the member variable and use it. @ State decorator to decorate:

 

@State list: string []=["Entry 1", "Entry 2", "Entry 3", "Entry 4", "Entry 5", "Entry 6"]
build() {
Column() {
Button ("Add Data"). onClick()=>{
This. list. push ("Item Seven")
This. list. push ("Item 8")
})
List({ space: 20, initialIndex: 0 }) {
ForEach(this.list, (item: string) => {
ListItem() {
Text(item)
.width('100%')
.height(50)
.fontSize(16)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
}
}, (item: string) => item)
}.padding({ left: 20, right: 20 })
.margin({ top: 20 })
}
}
Enter fullscreen mode Exit fullscreen mode

Image description

when we click the Append Data button, the normal situation will be to add data to the array to drive UI update, and the List component should add two pieces of data [entry 7, entry 8]. 

Indeed, after clicking, the UI changed and two pieces of data were added to the list: 

Image description

is there a problem? I 've said a lot. It's quite normal for the program not to be executed. Hey, don't be impatient. Let's click again. The normal program will add two pieces of data again, right? 

But here comes the question, no increase!!!, A hundred clicks did not increase.

Is it because duplicate data cannot be added repeatedly? This is ridiculous. There can be no duplicate data in the list, which is an unheard of spectacle in any system. 

Obviously these problems are not, the reason for the problem is that the third parameter of the loop: the keyGenerator.

The main contents of this paper are as follows: 

1 Understanding the Cycle ForEach/LazyForEach three parameters

2, understanding. Key-Value Generation Rules

3. It is forbidden to render unexpected situations

4. Correct use of key values

5, the use of relevant summary


understand the cycle. ForEach/LazyForEach three parameters 

ForEach

 

 (arr: Array<any>, itemGenerator: (item: any, index: number) => void, keyGenerator?: (item: any, index: number) => string): ForEachAttribute;
Enter fullscreen mode Exit fullscreen mode

LazyForEach

 

 (dataSource: IDataSource, itemGenerator: (item: any, index: number) => void, keyGenerator?: (item: any, index: number) => string): LazyForEachAttribute;
Enter fullscreen mode Exit fullscreen mode

the first parameter arr/dataSource is the data source, which is used to render UI data. It is very important. How much data is rendered and how much data is dynamically added is directly related to it. It can be any type of array source, such as object, string, value, etc. 

The second parameter, itemGenerator, is component generation function, the purpose of each element in the array to create a corresponding component, it is and the first data source is a one-to-one correspondence.

The third parameter keyGenerator is a key-value generating function, which generates a unique and persistent key value for each array item of the data source arr. Its return value can be defined by itself. If it is defined by itself, it must be unique. If it is not defined, it will be the default:(item: T, index: number) => { return index + '__' + JSON.stringify(item); }, the default can also meet most of the requirements, so, in the actual development, if you are difficult to decide the only, then directly use the default. The problem in the preface is that the key value is not unique.

II. Understanding key-Value Generation Rules 

Image description

by understanding the three parameters of the loop, we already know that the system will provide us with function parameters for setting the key value, which can be customized, of course, you can also use the default key value generation rule, that is item: Object, index: number) => { return index + '__' + JSON.stringify(item); }. 

In the actual rendering process, each array element generates a unique and persistent key value to mark the corresponding component, when the key value changes, the ArkUI framework will think that the current array element replacement or modification will recreate a new component based on the new key value. 

Key value generation rules directly affect the UI of data rendering, because the second parameter, the itemGenerator function, creates a component for each array item of the data source according to the key-value generation rules.

In the Demo of the preface, it can be found that the key value is the current data source, when the key values generated by different Array items according to the key value generation rules are the same, the framework considers that they are undefined and no new components are created at this time, that is why the Click does not create the component again. 

Of course, there is another situation, that is, to modify the existing data, for example, there are three pieces of data, and the third piece of data is modified to a new data source. In this case, the first two pieces of data, the ForEach will be reused for rendering, and the third will create a new component for the array item. 

III. Prohibit rendering of unexpected situations 

what is unexpected rendering? The Demo in the foreword is a typical case, the same key value exists, so no new component is created. In actual development, when using ForEach, you should try to avoid including index in the final key value generation rule or using non-unique rules as the key value. 

Four, the correct use of key values 

first of all, must to meet the uniqueness of the key value, there is no doubt that it must be set correctly. If an object is used, it is strongly recommended to use the unique value in the object, such as id, as the key value. 

If you use basic type data as the key value, you must ensure that the elements in the array are not repeated, otherwise there will be problems in the preface Demo. In addition, when using basic type key values, ForEach will recreate the components after changing the data source, which will cause some performance loss. 

According to the official interpretation, in useWhen ForEach, try not to mix it with LazyForEach, which is not officially recommend, remember! 

V. Use of Relevant Summaries 

in order to make the data rendering correct, please ensure the uniqueness of the third parameter key value, and unless necessary, it is not recommend to make the third parameter KeyGenerator function in the default state and include the data item index index in the key value generation rule.

Top comments (0)