vincent O
vincent O

Reputation: 538

Checking firestore real time changes

I am working with firestore real time in a map project, and it requires updating a users current location at x distance interval. However, the real time listener keeps refetching my own updates, thereby increasing my reads. I assume firestore real time updates the cache locally before sending to the server, is it possible to ignore fetching changes that are made by that user?

class Booking extends Component {
  constructor(props) {
   super(props);
   this.state = {
     isLoading: false,
     errorMessage: '',
   };
   this.unsubscribe = null;
 }

 componentDidMount() {
   this.getRealTimeData();
 }

 componentWillUnmount() {
    this.unsubscribe = null;
  }

 getRealTimeData = () => {
   this.fetchCompletedGigs();
 }

   fetchCompletedGigs = () => {
     const { userID } = this.props;
     this.props.bookingData([]);

     this.setState({ isLoading: true, errorMessage: '' });
     this.unsubscribe = Firebase.shared.fetchBooking('Bookings')
      .where('userID', '==', userID)
      .orderBy('d.CreatedAt', 'desc')
      .limit(20)
       .onSnapshot((querySnapshot) => {
         if (querySnapshot.empty) {
           this.setState({
             isLoading: false,
             errorMessage: "You currently don't have anybooking",
           });
           this.props.bookingData([]);
         }
         querySnapshot.docChanges().forEach(change => {
           const doc = change.doc;
           const item = doc.data();
           item.docId = doc.id;
           const list = [...this.props.bookings, item];
           this.setState({ isLoading: false, errorMessage: '' });
           if (change.type === 'added') {
             const filterList = _.uniqBy(list, 'docId');
             this.props.bookingData(filterList);
           } else if (change.type === 'removed') {
             const newData = list.filter(task => task.docId !== doc.id);
              const filterList = _.uniqBy(newData, 'docId');
             return this.props.bookingData(filterList);
           } else if (change.type === 'modified') {
             const newData = list.filter(task => task.docId !== doc.id);
             const newList = [...newData, item];
             const filterList = _.uniqBy(newList, 'docId');
             return this.props.bookingData(filterList);
           }
         }, err => {
           this.props.bookingData([]);
           console.warn(err);
            this.setState({
              isLoading: false,
              errorMessage: 'Error occurred while fetching your booking',
            });
          });
       }, err => {
         this.props.bookingData([]);
         console.warn(err);
          this.setState({
            isLoading: false,
            errorMessage: 'Error occurred while fetching your booking.',
          });
        });
   }

Upvotes: 0

Views: 280

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 600006

You can't prevent the onSnapshot listener from firing for local events. But you can detect those local events inside the callback, and ignore them there:

Firebase.shared.fetchBooking('Bookings')
  .where('userID', '==', userID)
  .orderBy('d.CreatedAt', 'desc')
  .limit(20)
  .onSnapshot((querySnapshot) => {
     ...
     querySnapshot.docChanges().forEach(change => {
       if (change.doc.metadata.hasPendingWrites) {
         ... handle the local event differently
       }
       else {
         ... handle normally
       }
     });
     ...
  });

Also see the Firebase documentation on detecting local changes.

Upvotes: 1

Related Questions