当某些项目在本机中渲染时如何执行功能?

时间:2020-02-18 07:34:09

标签: reactjs typescript react-native react-native-flatlist react-native-sectionlist

我有一个联系人列表,其中同时显示用户的设备和在线联系人。在线联系人api不会一次给我所有联系人。因此,我必须执行一些分页。我也正在获取所有设备联系人和在线联系人的第一页,并对它们进行排序以显示在节列表中,但是问题是,要加载更多联系人,我必须跟踪处于状态和渲染功能的最后一个项目我正在调用分页功能以加载更多联系人。然后,我正在更新获取的在线联系人的状态。但这是不安全的操作,是否有更好的方法来实现呢?

我想在特定项目呈现时执行一个函数,它可以更新状态。

以下是一些代码: ContactList.tsx

import React, { Component } from "react";
import {
    View,
    StyleSheet,
    SectionListData,
    SectionList,
    Text
} from "react-native";

import { Contact } from "../../models/contact";
import ContactItem from "./contact-item";

export interface ContactsProps {
    onlineContacts: Contact[];
    deviceContacts: Contact[];
    fetchMoreITPContacts: () => void;
}

export interface ContactsState {
    loading: boolean;
    error: Error | null;
    data: SectionListData<Contact>[];
    lastItem: Contact;
    selectedItems: [];
    selectableList: boolean;
}

class ContactList extends Component<ContactsProps, ContactsState> {
    private sectionNames = [];

    constructor(props: ContactsProps, state: ContactsState) {
        super(props, state);
        this.state = {
            loading: false,
            error: null,
            data: [],
            lastItem: this.props.onlineContacts[this.props.onlineContacts.length - 1]
        };
        for (var i = 65; i < 91; ++i) {
            this.sectionNames.push({
                title: String.fromCharCode(i),
                data: []
            });
        }
    }

    private buildSectionData = contacts => {
        this.sort(contacts);
        const data = [];
        const contactData = this.sectionNames;
        contacts.map(contact => {
            const index = contact.name.charAt(0).toUpperCase();
            if (!data[index]) {
                data[index] = [];
                contactData.push({
                    title: index,
                    data: []
                })
            }
            data[index].push(contact);
        });
        for (const index in data) {
            const idx = contactData.findIndex(x => x.title === index);
            contactData[idx].data.push(...data[index]);
        }
        this.setState({
            loading: false,
            error: null,
            lastItem: contacts[contacts.length - 1],
            data: [...contactData]
        });
    };

    private sort(contacts) {
        contacts.sort((a, b) => {
            if (a.name > b.name) {
                return 1;
            }
            if (b.name > a.name) {
                return -1;
            }
            return 0;
        });
    }

    componentDidMount() {
        const contacts = [].concat(
            this.props.deviceContacts,
            this.props.onlineContacts
        );
        this.buildSectionData(contacts);
    }

    componentDidUpdate(
        prevProps: Readonly<ContactsProps>,
        prevState: Readonly<ContactsState>,
        snapshot?: any
    ): void {
        if (this.props.onlineContacts !== prevProps.onlineContacts) {
            const from = this.props.itpContacts.slice(
                prevProps.onlineContacts.length,
                this.props.onlineContacts.length
            );
            this.buildSectionData(from);
        }
    }

    renderItem(item: any) {
        if (!!this.state.lastItem && !this.state.loading)
            if (item.item.id === this.state.lastItem.id) {
                this.setState({
                    loading: true
                });
                this.props.fetchMoreOnlineContacts();
            }
        return <ContactItem item={item.item} />;
    }

    render() {
        return (
            <View style={styles.container}>
                <SectionList
                    sections={this.state.data}
                    keyExtractor={(item, index) => item.id}
                    renderItem={this.renderItem.bind(this)}
                    renderSectionHeader={({ section }) =>
                        section.data.length > 0 ? (
                            <Text style={styles.sectionTitle}>
                                {section.title}
                            </Text>
                        ) : null
                    }
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    sectionTitle: {
        paddingBottom: 30,

        paddingLeft: 25,
        fontWeight: "bold",
        fontSize: 20
    }
});

export default ContactList;

1 个答案:

答案 0 :(得分:0)

是的,经过一番思考,我得到了答案。 我没有从fetchMoreContacts调用renderItem,而是将lastItem作为道具传递给ContactItem组件。 在构造函数中,我检查了项目是否为lastItem并调用了fetchMoreContact。 而且有效!