Как выполнить функцию, когда какой-то элемент рендерится в режиме native? - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть раздел списка контактов, в котором отображаются как пользовательские, так и онлайн-контакты пользователя. API контактов онлайн не дает мне все контакты сразу. Поэтому я должен реализовать некоторые нумерации страниц. Я также извлекаю все контакты устройства и первую страницу онлайн-контактов и сортирую их для отображения в списке разделов, но проблема в том, чтобы загрузить больше контактов, я должен отслеживать последний элемент, отображаемый в моем состоянии, и в функции рендеринга, которую я вызываю функцию нумерации страниц, чтобы загрузить больше контактов. а затем я обновляю состояние загруженного онлайн-контакта. Но это небезопасная операция, есть ли лучший способ добиться этого?

Я хочу выполнить функцию, когда отображается указанный элемент c, и он может обновить состояние.

Вот некоторый код: 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 голосов
/ 18 февраля 2020

Да, после некоторых мыслей я получил ответ, может быть. вместо вызова fetchMoreContacts из renderItem я передал lastItem в качестве реквизита компоненту ContactItem. и в конструкторе я проверил, является ли элемент lastItem и вызван ли fetchMoreContact. и это сработало!

...