0

ユーザーのデバイスとオンライン連絡先の両方を表示している連絡先のセクションリストがあります。オンラインの連絡先 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;

4

1 に答える 1