React Native FlatList

FlatList是我们项目中经常使用的一个组件,

下面简述下使用中要注意的问题

一、keyExtractor

keyExtractor的唯一性

/**
     * Used to extract a unique key for a given item at the specified index. Key is used for caching
     * and as the react key to track item re-ordering. The default extractor checks `item.key`, then
     * falls back to using the index, like React does.
     */
    keyExtractor?: (item: ItemT, index: number) => string;

/**
*用于在指定索引处提取给定项的唯一键。密钥用于缓存
*并作为跟踪项目重新订购的反应键。默认提取器检查'item.key',然后
*退回到使用索引,就像React一样。
*/

keyExtractor决定了子组件是否需要新建。只要有新的keyExtractor,那么就会构造新的子组件。

所以我们需要确保keyExtractor的唯一性,如果keyExtractor不唯一,就会出现莫名其妙的错误

一般我们有以下两种方式设置keyExtractor

1、依赖当前数据模型的唯一标记userId(此方案需要后台返回的数据ID是唯一的)

keyExtractor={(item)=>item.userId}

2、前端自己生成

let extraUniqueKey = () => Math.random().toString();

 

二、renderItem、ListHeaderComponent

renderItem、ListHeaderComponent组件封装成函数时,注意this的绑定,

如果不想考虑this的问题,建议直接使用箭头函数

详情参考:React Native bind函数 bind(this)

先看效果:

代码如下:

1、使用箭头函数(推荐)

    private showFlatList() {
        let dataList = this.props.listData
        if (dataList && dataList.length) {
            let extraUniqueKey = () => Math.random().toString();
            return (

                <FlatList
                    style={{
                        backgroundColor: '#ffffff',
                        height: (44 * (dataList.length > 5 ? 4 : dataList.length) + 44),
                        marginHorizontal: 15,
                        marginTop: 20,
                    }}
                    data={dataList}
                    renderItem={this.renderUserItem}
                    // keyExtractor={(item)=>item.userId}
                    keyExtractor={extraUniqueKey}
                    ListHeaderComponent={this.listHeaderView}
                    showsVerticalScrollIndicator={false}
                />
            );
        }
    }

    // 表头(箭头函数)
    listHeaderView = () => {
        return (
            <View style={{
                backgroundColor: '#E7F1FF',
                height: 44,
                flexDirection: 'row',
                justifyContent: 'space-around',
                alignItems: 'center',
            }}>

                <Text style={style.itemText}>{this.showStr()}</Text>
                <Text style={style.itemText}>来来来 </Text>

            </View>)
    }

    // 表格 (箭头函数)
    renderUserItem = (renderItem: ListRenderItemInfo<NotEvaUserModel>) => {
        let item: NotEvaUserModel = renderItem.item
        return (
            <View style={style.itemBg}>
                <Text style={style.itemText}>{this.showStr()}</Text>
                <Text style={style.itemText}>{item.userName}</Text>
            </View>
        )
    }

    showStr() {
        return '我是showStr函数'
    }

2、使用普通函数,且renderItem、ListHeaderComponent中使用到this(建议直接bind(this)

实际验证renderUserItem必须绑定this,listHeaderView不绑定this也可以(纯属走运,不推荐)

原因如下

这是因为都属于调用后执行且renderUserItem是有参函数,listHeaderView是无参函数且只会触发一次

详情参考:React Native 函数的调用

private showFlatList() {
        let dataList = this.props.listData
        if (dataList && dataList.length) {
            let extraUniqueKey = () => Math.random().toString();
            return (

                <FlatList
                    style={{
                        backgroundColor: '#ffffff',
                        height: (44 * (dataList.length > 5 ? 4 : dataList.length) + 44),
                        marginHorizontal: 15,
                        marginTop: 20,
                    }}
                    data={dataList}
                    renderItem={this.renderUserItem.bind(this)}
                    // keyExtractor={(item)=>item.userId}
                    keyExtractor={extraUniqueKey}
                    ListHeaderComponent={this.listHeaderView.bind(this)}
                    showsVerticalScrollIndicator={false}
                />
            );
        }
    }

    // 表头(普通函数)
    listHeaderView () {
        return (
            <View style={{
                backgroundColor: '#E7F1FF',
                height: 44,
                flexDirection: 'row',
                justifyContent: 'space-around',
                alignItems: 'center',
            }}>

                <Text style={style.itemText}>{this.showStr()}</Text>
                <Text style={style.itemText}>来来来 </Text>

            </View>)
    }

    // 表格 (普通函数)
    renderUserItem (renderItem: ListRenderItemInfo<NotEvaUserModel>) {
        let item: NotEvaUserModel = renderItem.item
        return (
            <View style={style.itemBg}>
                <Text style={style.itemText}>{this.showStr()}</Text>
                <Text style={style.itemText}>{item.userName}</Text>
            </View>
        )
    }

    showStr() {
        return '我是showStr函数'
    }

3、使用普通函数,且renderItem、ListHeaderComponent中未使用到this(不推荐

不用考虑this绑定的情况

private showFlatList() {
        let dataList = this.props.listData
        if (dataList && dataList.length) {
            let extraUniqueKey = () => Math.random().toString();
            return (

                <FlatList
                    style={{
                        backgroundColor: '#ffffff',
                        height: (44 * (dataList.length > 5 ? 4 : dataList.length) + 44),
                        marginHorizontal: 15,
                        marginTop: 20,
                    }}
                    data={dataList}
                    renderItem={this.renderUserItem}
                    // keyExtractor={(item)=>item.userId}
                    keyExtractor={extraUniqueKey}
                    ListHeaderComponent={this.listHeaderView}
                    showsVerticalScrollIndicator={false}
                />
            );
        }
    }

    // 表头(普通函数)
    listHeaderView () {
        return (
            <View style={{
                backgroundColor: '#E7F1FF',
                height: 44,
                flexDirection: 'row',
                justifyContent: 'space-around',
                alignItems: 'center',
            }}>

                <Text style={style.itemText}>我是showStr函数</Text>
                <Text style={style.itemText}>来来来 </Text>

            </View>)
    }

    // 表格 (普通函数)
    renderUserItem (renderItem: ListRenderItemInfo<NotEvaUserModel>) {
        let item: NotEvaUserModel = renderItem.item
        return (
            <View style={style.itemBg}>
                <Text style={style.itemText}>我是showStr函数</Text>
                <Text style={style.itemText}>{item.userName}</Text>
            </View>
        )
    }

}

const style = StyleSheet.create({

    bg: {
        backgroundColor: '#FFFFFF',
        borderRadius: 10,
        width: DeviceHelp.screenW - 100,
    },

    toptext: {
        fontWeight: 'bold',
        color: '#333333',
        marginTop: 20,
        textAlign: 'center',
        fontSize: DeviceHelp.fontSize(17)
    },

    centerText: {
        color: '#505A82',
        paddingTop: 15,
        paddingLeft: 15,
        paddingRight: 15,
        fontSize: DeviceHelp.fontSize(15)
    },

    itemBg: {
        height: 44,
        flexDirection: 'row',
        justifyContent: 'space-around',
        alignItems: 'center',
        backgroundColor: "#EFEFEF",
    },

    itemText: {
        color: '#333333',
        fontSize: DeviceHelp.fontSize(15),
    },

    line: {
        marginTop: 20,
        backgroundColor: '#99999955',
        height: 1,
    },

    btnText: {
        marginTop: 15,
        marginBottom: 15,
        color: "#3498FE",
        fontWeight: "bold",
        textAlign: "center",
        fontSize: DeviceHelp.fontSize(18),
    },


})

 综上:

推荐方案1和2

箭头函数直接使用,普通函数bind(this)

 

posted @ 2021-11-19 18:42  小菜看代码  阅读(318)  评论(0编辑  收藏  举报