React Native FlatList + Cloud Firestore错误:函数Query.startAfter()需要有效的第一个参数,但未定义

时间:2019-06-15 20:31:41

标签: reactjs firebase react-native google-cloud-firestore

我的代码可以工作并从Cloud Firestore检索数据(“ Component Did Mount” +“ retrieveData”)并设置状态,但是当React Native Flat List组件检索其他数据(retrieveMore)时,我需要传递先前的状态并追加文档数据到this.state.documentData。

该数据库包含20个文档,其ID从1到19。第一个查询检索9个文档,第二个查询检索9个文档,最后一个查询将返回1个文档(共19个)

当列表滚动到底部时,flatList将从Cloud Firestore获取其他文档,并将上一个查询中的最后一个可见文档作为起点。我可以将文件数据+ lastVisible获取到resolveMore函数,但是我无法弄清楚为什么使用.startAfter(this.state.lastVisible)查询将无法工作

我收到以下错误(来自retrieveMore函数): 函数Query.startAfter()需要一个有效的第一个参数,但未定义。

有效的方法:

  • ComponentDidMount可以正常工作(它调用retrieveData,该查询可以正常工作)
  • 使用setState + prevState将
  • documentData和lastVisible从RetrieveData传递到retreiveMore

错误所在的位置:

  • retrieveMore无法使用this.state.lastVisible作为从Cloud Firestore检索另外9个其他文档的起点

这是我的代码:

// Imports: Dependencies
import React, { Component } from "react";
import { ActivityIndicator, Dimensions, FlatList, SafeAreaView, StyleSheet, Text, View } from 'react-native';
import { usersRef } from '../App';

// Imports: Components
import ItemSelector from '../components/ItemSelector';
import Title from '../components/Title';

// Screen Dimensions
const { height, width } = Dimensions.get('window');

// Screen: InfiniteScroll
export default class InfiniteScroll extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      documentData: [],
      lastVisible: null,
      loading: false,
      refreshing: false,
    };
  }

  // Component Did Mount
  componentDidMount = () => {
    try {
      // Cloud Firestore: Initial Query (Infinite Scroll)
      this.retrieveData()
    }
    catch (error) {
      console.log(error);
    }
  }

  // Retrieve Data
  retrieveData = async () => {
    try {      
      // Set State: Loading
      // this.setState({ loading: true });

      this.setState((prevState) => {
        return ({...prevState, loading: true})
      })
      console.log('Retrieving Data');

      // Cloud Firestore: Query
      let initialQuery = await usersRef
        .where('id', '<=', 20)
        .orderBy('id')
        .limit(9)

      // Cloud Firestore: Query Snapshot
      let documentSnapshots = await initialQuery.get();

      // Cloud Firestore: Document Data
      let documentData = documentSnapshots.docs.map(document => document.data());
      console.log('Document Data (Retrieve Data)');
      console.log(documentData);

      // Cloud Firestore: Last Visible Document (To Start From For Proceeding Queries)
      let lastVisible = documentData[documentData.length - 1];
      console.log('Last Visible (Retrieve Data)');
      console.log(lastVisible);

      // Set State
      this.setState({
        documentData: documentData,
        lastVisible: lastVisible,
        loading: false,
      });
    }
    catch (error) {
      console.log(error);
    }
  }

  // Retrieve More
  retrieveMore = async () => {
    try {
      // Set State: Refreshing
      console.log('Retrieving additional Data');
      this.setState(prevState => ({
        documentData: prevState.documentData,
        lastVisible: prevState.lastVisible,
        refreshing: true,
      }));

      console.log('Previous State: Document Data');
      console.log(this.state.documentData);

      console.log('Previous State: Last Visible (Works Up Until Here. lastVisible works, but it doesn\'t work as the starting point for the additionalQuery)');
      console.log(this.state.lastVisible);

      // Cloud Firestore: Query (Additional Query)
      let additionalQuery = await usersRef
        .where('id', '<=', 20)
        .orderBy('id')
        .startAfter(this.state.lastVisible)
        .limit(9)

      // Cloud Firestore: Query Snapshot
      let documentSnapshots = await additionalQuery.get();

      // Cloud Firestore: Document Data
      let documentData = documentSnapshots.docs.map(document => document.data());
      console.log('Document Data (Retrieve More) (Post 2nd Query)');
      console.log(documentData);

      // Cloud Firestore: Last Visible Document (To Start From For Proceeding Queries)
      let lastVisible = documentData[documentData.length - 1];
      console.log('Last Visible (Retrieve More) (Post 2nd Query)');
      console.log(lastVisible);


      // Set State (Signature)
      this.setState(prevState => ({
        documentData: [...prevState.documentData, documentData],
        lastVisible: lastVisible,
        refreshing: false,
      }));
    }
    catch (error) {
      console.log(error);
    }
  }

  // Render Header
  renderHeader = () => {
    try {
      return (
        <Title title="Items" />
      )
    }
    catch (error) {
      console.log(error);
    }
  };

  // Render Footer
  renderFooter = () => {
    try {
      // Check If Loading
      // if (this.state.loading || this.state.refreshing) {
      if (this.state.loading) {
        return (
          <View style={styles.activityIndicator}>
            <ActivityIndicator />
          </View>
        )
      }
      else {
        return null;
      }
    }
    catch (error) {
      console.log(error);
    }
  };

  // Select Item
  selectItem = (item) => {
    try {
      console.log(`Selected: ${item.first_name}`)
    }
    catch(error) {
      console.log(error);
    }
  }

  render() {
    return (
      <SafeAreaView style={styles.container}>
        <FlatList
          // Data takes in an array
          data={this.state.documentData}
          // Render Items
          renderItem={({ item }) => (
            <ItemSelector
              item={item.first_name}
              // onPress={() => {this.selectItem(item)}}
            />
          )}
          // Element Key
          keyExtractor={(item, index) => String(index)}
          // Header (Title)
          ListHeaderComponent={this.renderHeader}
          // Footer (Activity Indicator)
          ListFooterComponent={this.renderFooter}
          // On End Reached takes in a function
          onEndReached={this.retrieveMore}
          // How Close To The End Of List Until Next Data Request Is Made
          onEndReachedThreshold={0}
          // Refreshing (Set To True When End Reached)
          refreshing={this.state.refreshing}
        />
      </SafeAreaView>
    )
  }
}

// Styles
const styles = StyleSheet.create({
  container: {
    height: height,
    width: width,
  },
  text: {
    fontFamily: 'System',
    fontSize: 16,
    fontWeight: '400',
    color: '#222222',
  },
});

console.log:retrieveData

Retrieving Data
Document Data (Retrieve Data)
Array [
  Object {
    "first_name": "Kristin",
    "id": 1,
    "last_name": "Smith",
  },
  Object {
    "first_name": "Olivia",
    "id": 2,
    "last_name": "Parker",
  },
  Object {
    "first_name": "Jimmy",
    "id": 3,
    "last_name": "Robinson",
  },
  Object {
    "first_name": "Zack",
    "id": 4,
    "last_name": "Carter",
  },
  Object {
    "first_name": "Brad",
    "id": 5,
    "last_name": "Rayburn",
  },
  Object {
    "first_name": "Ashley",
    "id": 6,
    "last_name": "Foster",
  },
  Object {
    "first_name": "Parker",
    "id": 7,
    "last_name": "Trotter",
  },
  Object {
    "first_name": "Kevin",
    "id": 8,
    "last_name": "Carter",
  },
  Object {
    "first_name": "Zack",
    "id": 9,
    "last_name": "Klein",
  },
]
Last Visible (Retrieve Data)
Object {
  "first_name": "Zack",
  "id": 9,
  "last_name": "Klein",
}

console.log:retrieveMore(直到附加查询为止)

Retrieving additional Data
Previous State: Document Data
Array [
  Object {
    "first_name": "Kristin",
    "id": 1,
    "last_name": "Smith",
  },
  Object {
    "first_name": "Olivia",
    "id": 2,
    "last_name": "Parker",
  },
  Object {
    "first_name": "Jimmy",
    "id": 3,
    "last_name": "Robinson",
  },
  Object {
    "first_name": "Zack",
    "id": 4,
    "last_name": "Carter",
  },
  Object {
    "first_name": "Brad",
    "id": 5,
    "last_name": "Rayburn",
  },
  Object {
    "first_name": "Ashley",
    "id": 6,
    "last_name": "Foster",
  },
  Object {
    "first_name": "Parker",
    "id": 7,
    "last_name": "Trotter",
  },
  Object {
    "first_name": "Kevin",
    "id": 8,
    "last_name": "Carter",
  },
  Object {
    "first_name": "Zack",
    "id": 9,
    "last_name": "Klein",
  },
]
Previous State: Last Visible (Works Up Until Here. lastVisible works, but it doesn't work as the starting point for the additionalQuery)
Object {
  "first_name": "Zack",
  "id": 9,
  "last_name": "Klein",
}
Document Data (Retrieve More) (Post 2nd Query)
Array []
Last Visible (Retrieve More) (Post 2nd Query)
undefined

0 个答案:

没有答案