【问题标题】:Do I need Pagination, Lazy Loading or none in my React-Native app?我的 React-Native 应用程序需要分页、延迟加载还是不需要?
【发布时间】:2019-10-29 00:15:31
【问题描述】:

我正在 React-Native 中实现一个应用程序,我在其中从 Cloud-Firestore 获取“餐厅”作为文档,并且我也在使用 onSnapshot() 侦听器。当应用程序准备好发布时,可能会有最多 3000 家餐厅。关于这个问题,我有几个问题要问。

-我是否需要实施分页/延迟加载以获得更好的用户体验和更低的成本,或者 3000 不是一个大数字,所以不会对性能产生太大影响?!

-如果我确实需要实现其中一个,我应该实现哪一个?

-如果我不需要,那么有没有办法在 React-Native 中获取时压缩 JSON 数据以节省空间?然后在用户请求时解压。

实施延迟加载时用户能否搜索餐厅?

编辑: 我设法实现了延迟加载并且它工作得很好,但是,使用snapshot() 监听器会使延迟加载毫无意义,但我必须使用它,因为我需要获取实时的新“餐厅”或“订单”。那么,什么否则我可以使用 snapshot() 代替吗?或者是否有办法仍然使用 snapshot() 但对代码稍作改动?

第二个问题:上述问题解决后,是否可以实现搜索餐厅?知道我正在使用延迟加载似乎很棘手。

  componentDidMount() {
        try {
            // Cloud Firestore: Initial Query
            this.retrieveData();
        }
        catch (error) {
            console.log(error);
        }
    };

    retrieveData = () => {
        try {
            this.setState({
                loading: true
            })

            var initialQuery = firebase.firestore().collection('restaurants')
                .orderBy('res_id')
                .limit(this.state.limit)

            //let documentSnapshots = await initialQuery.get();

            initialQuery.onSnapshot((documentSnapshots => {
                var All = documentSnapshots.docs.map(document => document.data());


                var lastVisible = All[All.length - 1].res_id;
                this.setState({
                    All: All,
                    lastVisible: lastVisible,
                    loading: false,
                });
            }));


        }
        catch (error) {
            console.log(error);
        }
    };

    retrieveMore = async () => {
        try {
            // Set State: Refreshing
            this.setState({
                refreshing: true,
            });

            // Cloud Firestore: Query (Additional Query)
            var additionalQuery = await firebase.firestore().collection('restaurants')

                .orderBy('res_id')
                .startAfter(this.state.lastVisible)
                .limit(this.state.limit)
            // Cloud Firestore: Query Snapshot
            var documentSnapshots = await additionalQuery.get();
            // Cloud Firestore: Document Data
            var All = documentSnapshots.docs.map(document => document.data());
            // Cloud Firestore: Last Visible Document (Document ID To Start From For Proceeding Queries)
            var lastVisible = All[All.length - 1].res_id;
            // Set State
            this.setState({
                All: [...this.state.All, ...All],
                lastVisible: lastVisible,
                refreshing: false,
            });
            console.log('Retrieving additional Data', this.state.All);
        }
        catch (error) {
            console.log(error);
        }
    };


    // Render Header
    renderHeader = () => {
        try {
            return (
                <Text style={styles.headerText}>Items</Text>
            )
        }
        catch (error) {
            console.log(error);
        }
    };
    // Render Footer
    renderFooter = () => {
        try {
            // Check If Loading
            if (this.state.loading) {
                return (
                    <ActivityIndicator />
                )
            }
            else {
                return null;
            }
        }
        catch (error) {
            console.log(error);
        }
    };
    render() {
        return (
            <SafeAreaView style={styles.container}>
                <FlatList
                    // Data
                    data={this.state.All}
                    // Render Items
                    renderItem={({ item }) => (
                        <View style={styles.itemContainer}>
                            <Text>(ID: {item.res_id}) {item.rest_name} {item.rest_location}</Text>
                        </View>
                    )}
                    // Item Key
                    keyExtractor={(item, index) => String(index)}
                    // Header (Title)
                    ListHeaderComponent={this.renderHeader}
                    // Footer (Activity Indicator)
                    ListFooterComponent={this.renderFooter}
                    // On End Reached (Takes a function)
                    onEndReached={this.retrieveMore}
                    // How Close To The End Of List Until Next Data Request Is Made
                    onEndReachedThreshold={0.1}
                    // Refreshing (Set To True When End Reached)
                    refreshing={this.state.refreshing}
                />
            </SafeAreaView>
        )
    }

【问题讨论】:

    标签: react-native pagination google-cloud-firestore lazy-loading infinite-scroll


    【解决方案1】:

    在这种情况下,分页和延迟加载是一回事。您将在获取新数据时切换页面或无限滚动,直到没有更多数据可获取。无论哪种情况,您都需要它。看这里https://firebase.google.com/docs/firestore/query-data/query-cursors

    由于分页只是您查询数据的一种方式,它不会影响您如何以其他方式使用这些数据,这意味着在您的数据库设计和安全规则设置正确的情况下确保您可以搜索餐厅

    不确定你是否应该使用 onSnapshot 监听器,因为它会在每次发生变化时返回整个集合,这否定了使用分页的全部意义

    编辑:

    关于实时更新:这取决于您要实时获取什么。是只有你加载的那些餐馆还是全部?想象一下,您的数据库中有 1.000.000 家餐厅,您肯定不想查询所有餐厅以进行实时更新。仅刷新当前加载的那些在 firestore 中是相当昂贵的操作,因为每次可见餐厅发生变化时(例如,当您滚动页面时)都需要取消并创建新订阅。所以这两种变体都不是一种选择

    您应该重新考虑您的应用设计 - 例如你真的需要实时跟踪每家注册餐厅的订单吗?也许你只想要那些你是雇员的人,还是只想要你附近的人?也许您应该重组您的数据库以将订单与餐厅分开,这样您就可以在仍然延迟加载餐厅的同时收听订单?

    【讨论】:

    • 感谢您的建议!请检查我的问题,我已经编辑并添加了我的代码,我设法实现了延迟加载,但正如你所说,在这种情况下,onsnapshot() 将毫无意义。因为我真的需要实时获取数据,我还能做些什么呢?
    • 再次感谢!这是我需要做的:我目前正在首页上的“react-native-snap-carousel”之一中显示餐厅,我总共有 2 个。另一个轮播正在显示最新的折扣,所以我需要倾听折扣集合的变化,因为会不断更新。然后我需要将最新的折扣显示为轮播的第一项。
    猜你喜欢
    • 1970-01-01
    • 2014-01-19
    • 2010-10-20
    • 2013-11-23
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多