keyExtractor of FlatList learning record in react native

Writing time: the end of the 20th or the beginning of the 21st. I can't remember the specific time
React native version: 0.63.2
Target platform: Android, iOS

FlatList is an important component in RN. We plan to make a series to systematically learn and sort out its use methods and precautions. This issue mainly records several use scenarios and corresponding phenomena of keyExtractor

Scenario 1:

The parent component maintains a set of complex list data. The keyExtractor takes the key value of each item in the list. After clicking the button, the data is updated.

The code is as follows:

//App.js
import React from 'react';
import {View, Button, FlatList} from 'react-native';
import Item from './Item';

export default class App extends React.Component {
    constructor() {
        super();
        this.state = {
            list: [
                {key: '1', data: {name: 'aaa', age: 11}},
                {key: '2', data: {name: 'bbb', age: 22}},
                {key: '3', data: {name: 'ccc', age: 33}},
                {key: '4', data: {name: 'ddd', age: 44}},
                {key: '5', data: {name: 'eee', age: 55}},
            ],
        };
        this.temp = [
            {key: '6', data: {name: 'fff', age: 66}},
            {key: '7', data: {name: 'ggg', age: 77}},
            {key: '8', data: {name: 'hhh', age: 88}},
        ];
    }

    render() {
        console.log('App_render()');
        return (
            <View>
                {this.renderButton()}
                {this.renderList()}
            </View>
        );
    }

    renderButton = () => {
        console.log('App_renderButton()');
        return <Button title={'RefreshData'} onPress={this.onButtonPress} />;
    };

    renderList = () => {
        console.log('App_renderList()');
        return (
            <FlatList
                data={this.state.list}
                renderItem={this.renderItem}
                keyExtractor={this.keyExtractor}
            />
        );
    };

    renderItem = ({item}) => {
        return <Item itemData={item} />;
    };

    onButtonPress = () => {
        this.setState({list: this.temp});
    };

    keyExtractor = (item) => {
        return item.key;
    };
}
//Item.js
import React from 'react';
import {Text} from 'react-native';

export default class Item extends React.Component {
    constructor(props) {
        super(props);
        console.log('Item_constructor()', 'key:', this.props.itemData.key);
    }

    render() {
        console.log('Item_render()', 'key:', this.props.itemData.key);
        return <Text>{this.props.itemData.data.name}</Text>;
    }
}

The console log is as follows:

LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_constructor() key: 1
LOG  Item_render() key: 1
LOG  Item_constructor() key: 2
LOG  Item_render() key: 2
LOG  Item_constructor() key: 3
LOG  Item_render() key: 3
LOG  Item_constructor() key: 4
LOG  Item_render() key: 4
LOG  Item_constructor() key: 5
LOG  Item_render() key: 5
->Click the button to trigger data update and re render the interface
LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_constructor() key: 6
LOG  Item_render() key: 6
LOG  Item_constructor() key: 7
LOG  Item_render() key: 7
LOG  Item_constructor() key: 8
LOG  Item_render() key: 8

Summary: if the data changes and the key value in the list is different from the original data, the sub component will trigger the constructor, that is, a new sub component will be generated

Scenario 2:

Similar to scenario 1, but set the keyExtractor to the name in the list data, and then observe the results

The code is modified as follows:

//App.js
keyExtractor = (item) => {
    return item.data.name;
};

The console log is as follows:

LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_constructor() key: 1
LOG  Item_render() key: 1
LOG  Item_constructor() key: 2
LOG  Item_render() key: 2
LOG  Item_constructor() key: 3
LOG  Item_render() key: 3
LOG  Item_constructor() key: 4
LOG  Item_render() key: 4
LOG  Item_constructor() key: 5
LOG  Item_render() key: 5
->Click the button to trigger data update and re render the interface
LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_constructor() key: 6
LOG  Item_render() key: 6
LOG  Item_constructor() key: 7
LOG  Item_render() key: 7
LOG  Item_constructor() key: 8
LOG  Item_render() key: 8

Summary: it can be seen that whether the keyExtractor is set as key or data.name in the data, as long as the data corresponding to the keyExtractor in the new data changes, the constructor will be triggered to create a new sub component. In other words, the creation of sub components is independent of the data level bound by keyExtractor.

Scenario 3:

When the data is updated, if the value corresponding to the keyExtractor of the new data has no new content, what about the sub component?

Based on scenario 1, the keyExtractor corresponds to the key value in the list data, and modifies the data this.temp used for updating. The modifications are as follows:

//App.js
this.temp = [
    {key: '1', data: {name: 'fff', age: 66}},
    {key: '2', data: {name: 'ggg', age: 77}},
    {key: '3', data: {name: 'hhh', age: 88}},
];

It can be seen that there is no new content in the key value, but the internal data has been completely modified. The final console log is as follows:

LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_constructor() key: 1
LOG  Item_render() key: 1
LOG  Item_constructor() key: 2
LOG  Item_render() key: 2
LOG  Item_constructor() key: 3
LOG  Item_render() key: 3
LOG  Item_constructor() key: 4
LOG  Item_render() key: 4
LOG  Item_constructor() key: 5
LOG  Item_render() key: 5
->Click the button to trigger data update and re render the interface
LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_render() key: 1
LOG  Item_render() key: 2
LOG  Item_render() key: 3

As can be seen from the above logs, no new sub components are generated

Scenario 4:

Based on scenario 3, if part of the new data contains a new key value

The codes to be replaced are as follows:

//App.js
this.temp = [
    {key: '1', data: {name: 'fff', age: 66}},
    {key: '6', data: {name: 'ggg', age: 77}},
    {key: '7', data: {name: 'hhh', age: 88}},
];

The log is as follows:

LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_constructor() key: 1
LOG  Item_render() key: 1
LOG  Item_constructor() key: 2
LOG  Item_render() key: 2
LOG  Item_constructor() key: 3
LOG  Item_render() key: 3
LOG  Item_constructor() key: 4
LOG  Item_render() key: 4
LOG  Item_constructor() key: 5
LOG  Item_render() key: 5
->Click the button to trigger data update and re render the interface
LOG  App_render()
LOG  App_renderList()
LOG  App_renderButton()
LOG  Item_render() key: 1
LOG  Item_constructor() key: 6
LOG  Item_render() key: 6
LOG  Item_constructor() key: 7
LOG  Item_render() key: 7

As can be seen from the log, the keyExtractor determines whether the sub component needs to be created. As long as there is a new keyExtractor, a new sub component will be constructed

Tags: Javascript React Native react-native

Posted on Sat, 20 Nov 2021 16:37:22 -0500 by Xager